Fórum

Why does LiferayFacesContext extend FacesContext?

thumbnail
Tobias Liefke, modificado 9 Anos atrás.

Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil (and other Liferay-Faces developers),

I've got a Question about the design of LiferayFacesContext: Why does it extend FacesContext?
  • It isn't replacing any existing FacesContext, it even does not stick to the API of that one - to have one FacesContext per thread. Instead the LiferayFacesContext instance is static.
  • All code that needs a FacesContext will stick to FacesContext.getCurrentInstance() and will still receive the default instance.
  • The API of FacesContext is polluting the API of LiferayFacesContext.
  • Even if you want the API of FacesContext in JSF expressions (e.g. #{liferayFacesContext...}) you could add these methods without extending FacesContext - but I would stick to the good old #{facesContext..} in that case.

Why is it even called "...Context" - it is more a ...Util or ...Helper (which it includes, I know)?

So there is (at least from my point of view) no advantage, instead it confuses users who know FacesContext from standalone JSF application.
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

The idea for LiferayFacesContext started back in 2007 if I remember correctly. When using Liferay Portal, JSF portlet developers were typically writing code like this:

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
ThemeDisplay themeDisplay = (ThemeDisplay) externalContext.getRequestMap().get(WebKeys.THEME_DISPLAY);


Consequently, developers needed to write their own JSFPortletUtil type of class full of static methods...

Because of this, we wanted to provide a convenient way for developers to get a single contextual object that would enable developers to access JSF, Portlet, and Liferay operations associated with the request.

LiferayFacesContext is a plain singleton that extends the FacesContext. When a method like liferayFacesContext.getViewRoot() is called, the LiferayFacesContext singleton simply delegates to the underlying FacesContext.getCurrentInstance() ThreadLocal singleton.


Kind Regards,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

yeah, I remember these times.

We developed such helper classes as well, called them ...Util and still use them - LiferayFacesContext doesn't contain all shortcuts and really doesn't need to provide all you can think of.

But all you mention doesn't answer my question: Why do you extend FacesContext?

I think a JSF developer should be aware of the FacesContext - so a LiferayFacesContext which is called like FacesContext, extends FacesContext but is in reality a helper class to access the functionality of FacesContext.getCurrentInstance (and more) is really confusing:
First you wonder about the difference between LiferayFacesContext.getInstance() and LiferayFacesContext.getCurrentInstance().
Then you wonder why FacesContext.getCurrentInstance() is not returning an instance of LiferayFacesContext.
And if you have made heavy use of LiferayFacesContext you wonder, why you can't replace LiferayFacesContext with a wrapper, like you can do it with any other FacesContext. For example if you want to replace some functionality for a specific request.

So you break with the design pattern of a "context" by using a singleton, you break with the contract of "is a faces context" by using a singleton that is not the one from FacesContext.getCurrentInstance() and you receive no benefit by extending FacesContext.

Furthermore you don't really need a "one stop shop" for "access JSF, Portlet, and Liferay operations associated with the request". As a JSF and portlet developer I should distinguish between JSF specific functions (and use FacesContext.getCurrentInstance for that), Portlet specific functions (and use something like your PortletHelper for that) and Portal specific functions (like LiferayPortletHelper). That all of these are using the current FacesContext is implementation specific - and shouldn't be a point to extend FacesContext.
thumbnail
David H Nebinger, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 14914 Data de Entrada: 02/09/06 Postagens Recentes
It is often easy with hindsight to look back and say things should have been done differently, and some choices will be a matter of developer preferences or common practice at the time.

What's done is done. You can't roll back the clock and change something that was defined and established so long ago.

Is there some sort of issue that you're actually running into outside of not liking this implementation choice?

For all of your arguments, they seem to be related to how an inexperienced developer would look at LiferayFacesContext and have questions about it. I mean, not understanding that FacesContext.getCurrentInstance() is also returning a singleton? Yes, it actually is, and that there is no strange "context" design pattern that's being broken or violated.

And the missing thing is that hey, if you don't like LiferayFacesContext, well then you can stop using it and go back to your own ...Util class. It's certainly not required, it was meant to make dev's lives easier, but if you don't want to leverage it, then don't.
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Looking towards the future, perhaps we should look to JSF 2.3 for some guidance. Manfred Riem (co-spec lead of JSR 372) and maintainer of Mojarra has been blogging about new features in JSF 2.3 regarding the ability to use CDI to @Inject lots of different things, like:

@Inject javax.faces.context.FacesContext facesContext;
@Inject javax.faces.context.ExternalContext externalContext;
@Inject javax.faces.component.UIViewRoot uiViewRoot;
@Inject javax.faces.application.Application application;
@Inject java.util.Map<string, object> applicationMap;</string,>


Maybe we could follow this example and make it so that can do things like this:

@Inject com.liferay.portal.theme.ThemeDisplay themeDisplay;


If CDI is not present, then we could use the JSF 2.x @ManagedProperty way of injection (with an accompanying setter) instead.

If these injectable items were implemented as @RequestScoped beans (wrappers/pseudo-proxies), then they would be available via the EL as well:

#{themeDisplay.user)


That way, we have the benefit of getting access to contextual information without combining things like PortletHelper and FacesContext into a monolithic LiferayFacesContext.

Example proxy code:

@ManagedBean(name = "themeDisplay")
@RequestScoped
public class ThemeDisplayImpl extends ThemeDisplayWrapper {

	@Override
	public ThemeDisplay getWrapped() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		Map<string, object> requestMap = externalContext.getRequestMap();

		return (ThemeDisplay) requestMap.get(WebKeys.THEME_DISPLAY);
	}
}</string,>
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

as we have an CDI application, I've tried to inject the ThemeDisplay:

public class Resources {

	@Produces
	@RequestScoped
	public PortletRequest getPortletRequest() {
		return ((PortletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest());
	}

	@Produces
	@RequestScoped
	public PortletPreferences getPortletPreferences() {
		return getPortletRequest().getPreferences();
	}

	@Produces
	@RequestScoped
	public ThemeDisplay getThemeDisplay() {
		return (ThemeDisplay) getPortletRequest().getAttribute(WebKeys.THEME_DISPLAY)
	}
...
}


public class PortletBean {
	@Inject
	private ThemeDisplay themeDisplay;

	public void doSomeAction() {
		long companyId = this.themeDisplay.getCompanyId();
		....
	}
}


That's something that helps us a lot, especially for the usecases I mentioned.

Thanks for that idea.
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
It was my pleasure Tobias. I'm glad to hear that you like the idea and that it is working.

In order to make injection of dependencies like ThemeDisplay available to non-JSF portlets, we might put the producers in the Liferay cdi-portlet-bridge-shared.jar artifact, rather than in the liferay-faces-portal.jar artifact. Also, we might use CDI dynamic producers, similar to the JSF 2.3 FacesContextProducer.java class.

But since not everyone uses CDI, we also want to make injection available via the JSF @javax.faces.bean.ManagedProperty or @javax.inject.Inject via Spring. Clearly we have a lot to think about...

Finally, if injection is the preferred way of achieving developer convenience, we might consider moving LiferayFacesContext to a liferay-faces-portal-legacy.jar project. We did this type of thing for the Liferay 6.2 + JSF 1.2 (2.2.x) branch with the liferay-faces-legacy.jar project.

What do you think about the legacy jar idea?
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

I'm fine with the legacy jar idea - it is somehow a "harder" deprecation than just the keyword.

Are you planning to use your own annotation for injection, or why would you like to use dynamic producers?

I've never used cdi-portlet-bridge-shared.jar - up til now my CDI projects are working without it. Do I still need it, if I'm using JBoss 7.x?

Tobias
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

Tobias Liefke:
Are you planning to use your own annotation for injection, or why would you like to use dynamic producers?


We are considering deprecating the following application-scoped singletons:



And replacing them with the following ThreadLocal singletons, respectively:

  • com.liferay.faces.util.context.FacesRequestContext
  • com.liferay.faces.portal.context.LiferayRequestContext.java


Being ThreadLocal, they would basically have the same scope as FacesContext (and also the same as the PrimeFaces RequestContext). The Mojarra 2.3 reference implementation chose to use CDI Dynamic Producers, so we will probably follow that decision. I think the decision was made because it helps with generics. For more information, see Arjan Tijms article Dynamic CDI producers.

Tobias Liefke:
I've never used cdi-portlet-bridge-shared.jar - up til now my CDI projects are working without it. Do I still need it, if I'm using JBoss 7.x?


The cdi-portlet-bridge-shared.jar was developed in order to provide alignment between CDI and Portlets. For more information, see Developing JSF Portlets with CDI.

Kind Regards,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

Tobias Liefke:
I've never used cdi-portlet-bridge-shared.jar - up til now my CDI projects are working without it. Do I still need it, if I'm using JBoss 7.x?


Neil Griffin:
The cdi-portlet-bridge-shared.jar was developed in order to provide alignment between CDI and Portlets. For more information, see Developing JSF Portlets with CDI.


I've read the mentioned page, but I still don't know if I need it, at least for my projects which make heavy use of CDI. Maybe Weld and the WeldCrossContextFilter of JBoss are already doing that job...

Tobias
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

Tobias Liefke:
I've read the mentioned page, but I still don't know if I need it, at least for my projects which make heavy use of CDI. Maybe Weld and the WeldCrossContextFilter of JBoss are already doing that job...


In our test environments, we were not able to make Liferay + JSF + JBoss AS7 + Weld work without it, since Weld had some casts to HttpServletRequest that were causing ClassCastExceptions with PortletRequest.

May I ask what version of JBoss AS7 and what version of Weld you are using in your environment?

Thanks,

Neil
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

I also wanted to mention that Ken Finnigan of JBoss mentioned in PBR-519 that the ClassCastException problems in Weld 1.x seem to have been addressed in Weld 2.x.

Kind Regards,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

we are using JBoss AS 7.2 / JBoss EAP 6.1, which still contains Weld 1.1

With this definition of WelcCrossContextFilter everything is working fine:

<!-- Weld context filter -->
<filter>
<filter-name>WeldCrossContextFilter</filter-name>
<filter-class>org.jboss.weld.servlet.WeldCrossContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>WeldCrossContextFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>

Tobias
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

When you get a chance, I would be very interested to know the exact version of JBoss Weld that you are using in your EAP 6.1 environment. You can determine the version by examining the contents of $JBOSS_HOME/modules/org/jboss/weld/core/main/module.xml

Thanks,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

versions are not defined in the module.xml, but from the file name I would guess it's 1.1.10.final:
weld-core-1.1.10.Final.jar
emoticon

Tobias
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

Thanks for reporting back. I am happy to learn that you are using Weld 1.1.10 since that is the version we tested Liferay Faces with, but I am very surprised that you do not encounter the ClassCastException problems as we do with JBoss 7.1. Perhaps JBoss 7.2 has remedied this problem in some way.

Kind Regards,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

if you send me the stacktrace of the ClassCastException I could have a look at it and check what happens at that code line for our environment.

Maybe its Liferay, which has changed something? We are using 6.2.1.

Tobias
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

I just deployed the jsf2-cdi-portlet.war demo on JBoss AS without the cdi-portlet-bridge-shared.jar dependency, and without the extra stuff added to WEB-INF/web.xml and WEB-INF/portlet.xml as specified in the Developing JSF Portlets with CDI wiki article.

I am happy to report that I wasn't able to reproduce the ClassCastException. emoticon

If you encounter any problems with Liferay + JSF + Weld in the future, please let us know.

Kind Regards,

Neil
thumbnail
Neil Griffin, modificado 8 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
I just wanted to provide everyone with an update: Today we committed changes to our new liferay-faces-util.git and liferay-faces-portal.git repositories for FACES-2502. With these changes, LiferayFacesContext and ExtFacesContext are now deprecated. Please see the details of FACES-2502 for more information.
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi David,

first of all please don't take my question personally - I didn't want to question the whole API.
I'm developing Liferay applications with JSF since 2005, so I still remember how the first implementation of the bridge by Sun did work - or did not work.
So kudos to Neil and the whole Liferay-Faces Team who manage to build a bridge which integrates smoothly and keep that up to date with any JSF and Liferay version.

I had indeed some issues, which would have easy been fixed by using a wrapper around the current LiferayFacesContext. But thats not the point - if it really would be an issue of the API I would have opened a report in JIRA. I just wanted to know why it is extending FacesContext without any needs - thats something I still don't understand (except you think that "What's done is done." is such an answer).

I can't stop using LiferayFacesContext, because for example LiferayFacesContext.getThemeDisplay() is implementation specific - so there is a need for something like LiferayPortletHelper which is available for a specific version of Liferay - btw. is there something similar available for non JSF portlets?

So the answer of Neil is something which I had in mind and I would really love to see someday.

Last thing - I can't resist: If you think FacesContext.getCurrentInstance() is returning a singleton - than one of us should check his definition of singletons. And there is a "context" design pattern, at least in my book of Core J2EE Patterns (despite that one is a bit old, indeed).
thumbnail
David H Nebinger, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 14914 Data de Entrada: 02/09/06 Postagens Recentes
Tobias Liefke:
first of all please don't take my question personally - I didn't want to question the whole API.


No problem, it was just that the tone towards Neil seemed a little harsh and I felt I had to jump in. Neil is the most dedicated and committed advocate for JSF on the portal, participates in many of the portal-related JCPs, etc., that I think he deserves a great deal of respect (he has mine, anyway).

I had indeed some issues, which would have easy been fixed by using a wrapper around the current LiferayFacesContext. But thats not the point - if it really would be an issue of the API I would have opened a report in JIRA. I just wanted to know why it is extending FacesContext without any needs - thats something I still don't understand (except you think that "What's done is done." is such an answer).


The issue here is that the change is so old, there's lots of legacy code out there now that is dependent upon LiferayFacesContext. Even if we all agree that the name is wrong or the extends FacesContext is gone, etc., if it were to change there would be a lot of developers up in arms over it (i.e. I was reading in Reddit yesterday the backlash that is arising out of the Angular changes coming in 2.0).

So now it's a question of whether it is worth changing the name or removing the extension, facing the backlash that will arise, or whether it is better to simply acknowledge that although things might be "better" if it were to change, since it works it's better not to fix it.

I can't stop using LiferayFacesContext, because for example LiferayFacesContext.getThemeDisplay() is implementation specific - so there is a need for something like LiferayPortletHelper which is available for a specific version of Liferay - btw. is there something similar available for non JSF portlets?


Implementation specific in what way? ThemeDisplay has changed between versions, but the ThemeDisplay class has remained a constant. Or is it the access to ThemeDisplay? LiferayFacesContext.getThemeDisplay() is pretty simple:

public ThemeDisplay getThemeDisplay() {
  ThemeDisplay themeDisplay = (ThemeDisplay) getPortletRequest().getAttribute(WebKeys.THEME_DISPLAY);

  return themeDisplay;
}


As far as something similar for non-JSF, well it's always gotten to by the same way, grabbing the THEME_DISPLAY attribute from the incoming request object.

Last thing - I can't resist: If you think FacesContext.getCurrentInstance() is returning a singleton - than one of us should check his definition of singletons.


MyFaces (and others) implement a singleton bound to a thread. See http://svn.apache.org/repos/asf/myfaces/core/trunk/api/src/main/java/javax/faces/context/FacesContext.java for their current implementation. Disputing a classic singleton vs a thread-based singleton doesn't get us anywhere, but I think we can at least agree that, from the perception of code running within the thread, the singleton instance is the same shared instance that any code within the thread would have access to.

Even though the LiferayFacesContext seems to use a classic singleton, it is also decorated with the transient keyword as it actually changes with the thread. So the LiferayFacesContext is not a classic singleton, either.
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi David,

first of all I did not ask to change the current implementation or naming - wait a moment - no I didn't. In that case I would have opened a CR in JIRA. I just wanted to understand the reason. That's why I marked this as question and I still didn't get an answer on that.
You don't need to extend a list to build a helper class for a list, so why extending FacesContext to build a helper class for the current FacesContext?
All things I said in my first and second post was that I only see the disadvantages of that.

ThemeDisplay themeDisplay = (ThemeDisplay) externalContext.getRequestMap().get(WebKeys.THEME_DISPLAY);

The access to ThemeDisplay was only one example, but we can stay with that one: Let's assume I did build my portlet app against Liferay 6.1. Now I deploy the app in Liferay 6.2. So I have to replace the bridge for 6.1 with that one for 6.2. When using LiferayFacesContext thats it. When using my own Util as you propose, I have to rebuild my application. Why? Because WebKeys.THEME_DISPLAY has changed between 6.1 and 6.2. So even that small example is implementation specific. And there is no guarantee that the implementation stays the same, just because it always had be.

MyFaces (and others) implement a singleton bound to a thread
...
the singleton instance is the same shared instance that any code within the thread would have access to

Let's assume that there is something like a singleton which may differ per thread (as far as I can see that is something that would explicitly brake the singleton pattern). But that is the point, where you missunderstand the definition of a context in common - and the implementation of FacesContext in detail. The result of FacesContext.getCurrentInstance() won't stay the same for the same thread - it even doesn't need to stay the same for the same server request. The only guarantee you have is, that it stays the same during the runtime of one of your methods.

Even though the LiferayFacesContext seems to use a classic singleton, it is also decorated with the transient keyword as it actually changes with the thread. So the LiferayFacesContext is not a classic singleton, either.

I don't get it. What has a transient field to do with threads? Transient is marking a field which doesn't take part in serialization. Did you think of volatile?
You are right, that LiferayFacesContext is not a straight singleton, as it offers setInstance(). But as far as I understand that's only an implementation specific side effect of the instantiation using an application scoped bean.
thumbnail
Neil Griffin, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
Hi Tobias,

Tobias Liefke:
I just wanted to understand the reason. That's why I marked this as question and I still didn't get an answer on that.


Sorry, I thought I had answered your question about why LiferayFacesContext extends FacesContext when I wrote:

Neil Griffin:
we wanted to provide a convenient way for developers to get a single contextual object that would enable developers to access JSF, Portlet, and Liferay operations associated with the request.


You make a good point about the confusion between LiferayFacesContext.getInstance() and LiferayFacesContext.getCurrentInstance(). But since this is legacy code we are unable to change the inheritance hierarchy.

Moving forward, I think it would be good if we used dependency injection via @Inject (CDI) and/or @ManagedProperty (JSF) in order to obtain contextual objects (like ThemeDisplay) that have a smaller footprint and don't try to do too much (like the monolithic LiferayFacesContext).


Kind Regards,

Neil
thumbnail
Tobias Liefke, modificado 9 Anos atrás.

RE: Why does LiferayFacesContext extend FacesContext?

Junior Member Postagens: 78 Data de Entrada: 23/11/12 Postagens Recentes
Hi Neil,

I understand the point that you wanted to have a single helper object. All what I'm saying is, that it is not necessary to extend FacesContext for that purpose.
Just imagine to remove "extends FacesContext" and add the interesting methods (getAttributes(), getExternalContext(), ...) to FacesContextHelper. I would think that this would not break existing code, as I don't think that somebody uses LiferayFacesContext where a FacesContext is requested. No, I don't want to do that, as I know that it will break the API nevertheless.

We can stop the discussion here, as I already can see the bright future emoticon : I really would like to see the injection idea some day, as that would make it easier to use the same beans in non JSF contexts - e.g. for unit tests, servlet requests, Message/Model/...Listener.

@David: Wait a moment, CDI - that rings a bell - what was the C in there? Maybe is is not only me who has a specific idea of "contexts"...