You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Kamil Soboń <is...@gmail.com> on 2011/06/13 21:23:17 UTC
JSF + OSGi integration.
Hi all,
I don't know if I am writing in appropriate place, but assume that I am ;)
So ... for some time, me and my friend are trying to create JSF
application in OSGi environment.
This application should be composed form core element and it's plug-ins.
Each plug-in (OSGi bundle) can be install installed or uninstalled in
run-time. Application should be aware of its plug-ins and its lifecycle
(installing/uninstalling) without being restarted.
To do so, we are combining few technologies: JSF (MyFaces) + PrimeFaces
+ Hibernate + Spring + OSGi (Equinox) + SpringDM (will be exchange to
blueprint).
To simplicy prototype we are going to use JSF + Spring + Spring-DM +
OSGi only.
As we have realized, JSF has not been planned to work with dynamic
components (plug-ins) that can provide new views (xhtml pages),
resources or manageable-beans. But specification of JSF allows to swap
some application's modules/components.
I have figure out some mechanism for providing views and resources
(manageable beans is quite more complicated and it is not part of my
question now :)) in run-time without violate JSF specification (in my
opinion ofcourse :)).
So our application is working in OSGi environment. The core is typical
JSF application deployed to Tomcat (thanks to Spring-DM) which is also
running in OSGi environment. Each plug-in is simply OSGi bundle that has
dependency to Core. In Core there is PluginsResolverService that is
responsible for detecting Core's available plug-in (assume that we are
keeping Bundle descriptor).
To provide views and resources in run-time (it is actuali working !) I
have done 2 things:
1) I have implemented my own ExternalContext and ExternalContextFactory.
Now we want to be aware of OSGi context not only about Servlet context,
I have implemented:
OsgiAwareExternalContextFactory which is quite simmilar to default
implementation. There are 2 differences. This class in constructor
requires ExternalContextFactory (decorator design pattern <- it is part
of JSF specification). The second difference is that we thos factory
provides OsgiAwareExternalContext that in constructor requires
ExternalContext (which we can obtain from original ExternalContextFactory).
OsgiAwareExternalContext (so far) delegates all of its method to
original ExternalContext except of getResource(String) method. This
method is using PluginsResolverService to obtain all plug-ins and to
look if they are not containing resource that we are looking for.
2) I have implemented my own Servlet for handling non-faces request of
resources.
That is all. Now if i'am installing plug-in that provides view:
someView.xhtml, I'am able to display it (I'am typing in web browser:
{Context path of Core}/someView.xhtml). But there is one problem. JSF
caches views. So if plug-in will be uninstalled, page someView.xhtml is
still visible for users.
I have found that DefaultFaceletFactory is responsible for caching
views. And here is my question.
If I want to provide my own FaceletFactory implementation I have to
provide brand new implementarion of ViewDeclarationLanguageFactory !!!
Standard implementation of ViewDeclarationLanguageFactory which is
ViewDeclarationLanguageFactoryImpl creates in initialize() method
FaceletViewDeclarationLanguageStrategy that is creating in constructor
FaceletViewDeclarationLanguage that is creating in initialize() method
FaceletFactory (DefaultFaceletFactory).
FaceletViewDeclarationLanguage has protected method
createFaceletFactory(FacesContext, Compiler) (wchich is called in
initialize() method) that is responsible for creating FaceletFactory.
But even it is protected method that I Can override I cannot provide my
own implementation of ViewDeclarationLanguageBase (which will extends
FaceletViewDeclarationLanguage) because there is no way of informing
FaceletViewDeclarationLanguageStrategy thats should use my
implementation. Shouldn't it be possible ?
Sorry for my English :)
--
Pozdrawiam,
Kamil Soboń
iso.poczta(at)gmail.com
sobon(at)student.agh.edu.pl
Re: JSF + OSGi integration.
Posted by Kamil Soboń <is...@gmail.com>.
W dniu 2011-06-14 11:46, Jakob Korherr pisze:
> Hi,
>
> Actually you should not directly use stuff from myfaces-impl (package
> org.apache.myfaces.*). Theses classes are implementation specific and
> not built for extensions!
>
> If you need some base code, you should copy (or shade) it!
>
> Regards,
> Jakob
>
It is impossible (or only I cannot find a way) to provide my own
FaceletCache in approach that you suggest.
If I want to provide my own implementation of FaceletCache (suppose:
MyFaceletCache) I am also obligated to provide implementation of
Facelet. I cannot use DefaultFacelet class due to the fact that it is
final has package access and is placed in myfaces-impl. So I am creating
MyDefaultFacelet (copy-paste from DefaultFacelet). Now I am bound to
DefaultFaceletContext. Due to the fact that I cannot use
DefaultFaceletContext (the same story: final, package class and placed
in myfaces-impl). So I am creating MyDefaultFaceletContext (copy-paste
from DefaultFaceletContext). Now everything should be ok (despite the
fact that now I am resposible for maintaining code of MyFaceleteCache,
MyDefaultFacelet and MyDefaultFaceletContext. And every [brilliant]
change that will be made I have to recreate in my code).
But it is not working ! Why ? Lets look into constructor of
DefaultFaceletFactory (DefaultFaceletFactory(Compiler, ResourceResolver,
long)). Lines 131-134
Method setMemberFactoriesMethod =
FaceletCache.class.getDeclaredMethod("setMemberFactories", new
Class[]{FaceletCache.MemberFactory.class,
FaceletCache.MemberFactory.class});
setMemberFactoriesMethod.setAccessible(true);
setMemberFactoriesMethod.invoke(_faceletCache, faceletFactory,
viewMetadataFaceletFactory);
faceletFactory and viewMetadataFaceletFactory are created in those
constructor and are bound to those class.
This lines makes that my FaceletCache (MyFaceletCache) is bound to
DefaultFaceletFactory, so in fact I am bound to DefaultFacelet. So how I
can provide my own FaceletCache that is not bound to DefaultFacelet ?
Of course normally if I could put MyFaceletCache in
org.apache.myfaces.view.facelets.impl package. Now I can implement my
own MyFaceletCache that is extending FaceletCache<DefaultFacelet>.
I am not extending anything but using appropriate implementation of
Facelet. But in OSGi it is impossible to do so. Even if I put my class
in appropriate package, class MyFaceletCache and DefaultFacelet will be
loaded by different ClassLoaders and in fact will not be considered to
be placed in the same package. As a result IllegalAccessError will be
thrown.
The only solution for me, is to make class DefaultFaclet public
(DefaultFacletContext also ?). Will it broke some security or
architectonical assumptions ?
I hope that you can understand what I have written. If not, please
describe whuch part is not clear to you. I will try to describe the
problem in other way.
--
Pozdrawiam,
Kamil Soboń
iso.poczta(at)gmail.com
sobon(at)student.agh.edu.pl
Re: JSF + OSGi integration.
Posted by Kamil Soboń <is...@gmail.com>.
In JSF 2.1 FaceletCache has been created and provided for custom caching
and mapping URL (of view) to Facelet.
Why simmilar assumption has not been done for mapping uri of view to its
physical URL ?
I am talking about DefaultFaceletFactory#getViewMetadataFacelet(String)
method where _relativeLocations class field is use to cache mappings
between view's uri to its physical location.
I can only guess that, it hasn't been done due to the fact, that we are
not handling the situation when physically view (xhtml page) can
disappear. But if myfaces provides now libraries that can be used in
OSGi environemnt, we can provide fragemnts for main JSF application. If
so, those fragments can contains views. Fragments can be uninstalled in
run-time, so pages can disappear. Shouldn't we handle it ? If I am
thinking wrong ?
--
Pozdrawiam,
Kamil Soboń
iso.poczta(at)gmail.com
sobon(at)student.agh.edu.pl
Re: JSF + OSGi integration.
Posted by Jakob Korherr <ja...@gmail.com>.
Hi,
Actually you should not directly use stuff from myfaces-impl (package
org.apache.myfaces.*). Theses classes are implementation specific and
not built for extensions!
If you need some base code, you should copy (or shade) it!
Regards,
Jakob
2011/6/14 Kamil Soboń <is...@gmail.com>:
> W dniu 2011-06-14 01:30, Jakob Korherr pisze:
>>
>> Hi,
>>
>> Nice stuff ;)
>>
>> I think JSF 2.1 might have the answer to your problem. Two new classes
>> were introduced: FaceletCache and FaceletCacheFactory (see [1] and
>> [2]). With a custom impl of those two you should be able to control
>> the caching behavior!
>>
>> Regards,
>> Jakob
>>
>> [1]
>> http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCache.html
>> [2]
>> http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCacheFactory.html
>>
>> 2011/6/13 Kamil Soboń<is...@gmail.com>:
>>
>
> I have encountered some problems.
> I have investigated default implementation of FaceleteCache
> (FaceletCacheImpl) that is caching DefaultFacelet.
> Natural solution for me to provide my smart Facelet caching system that is
> aware of OSGi is to extend FaceletCacheImpl and provide new implementation
> of needsToBeRefreshed(DefaultFacelet) method. But it is not possible due to
> the fact that both classes has default (package) access modifier. In order
> to have access in using this classes i should put my own new implementation
> in org.apache.myfaces.view.facelets.impl package. But OSGi is throwing
> IllegalAccessError.
> I also cannot provide new implementation of FaceletCache (that bases on
> FaceletCacheImpl - simply copy&paste) due to the fact I want to use
> DefaultFacelete, which has also default (package) access modifier.
>
> Here is my question: why those classes has default (not public) access level
> ?
>
> --
> Pozdrawiam,
> Kamil Soboń
>
> iso.poczta(at)gmail.com
> sobon(at)student.agh.edu.pl
>
>
--
Jakob Korherr
blog: http://www.jakobk.com
twitter: http://twitter.com/jakobkorherr
work: http://www.irian.at
Re: JSF + OSGi integration.
Posted by Kamil Soboń <is...@gmail.com>.
W dniu 2011-06-14 01:30, Jakob Korherr pisze:
> Hi,
>
> Nice stuff ;)
>
> I think JSF 2.1 might have the answer to your problem. Two new classes
> were introduced: FaceletCache and FaceletCacheFactory (see [1] and
> [2]). With a custom impl of those two you should be able to control
> the caching behavior!
>
> Regards,
> Jakob
>
> [1] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCache.html
> [2] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCacheFactory.html
>
> 2011/6/13 Kamil Soboń<is...@gmail.com>:
>
I have encountered some problems.
I have investigated default implementation of FaceleteCache
(FaceletCacheImpl) that is caching DefaultFacelet.
Natural solution for me to provide my smart Facelet caching system that
is aware of OSGi is to extend FaceletCacheImpl and provide new
implementation of needsToBeRefreshed(DefaultFacelet) method. But it is
not possible due to the fact that both classes has default (package)
access modifier. In order to have access in using this classes i should
put my own new implementation in org.apache.myfaces.view.facelets.impl
package. But OSGi is throwing IllegalAccessError.
I also cannot provide new implementation of FaceletCache (that bases on
FaceletCacheImpl - simply copy&paste) due to the fact I want to use
DefaultFacelete, which has also default (package) access modifier.
Here is my question: why those classes has default (not public) access
level ?
--
Pozdrawiam,
Kamil Soboń
iso.poczta(at)gmail.com
sobon(at)student.agh.edu.pl
Re: JSF + OSGi integration.
Posted by Kamil Soboń <is...@gmail.com>.
W dniu 2011-06-14 01:30, Jakob Korherr pisze:
> Hi,
>
> Nice stuff ;)
>
> I think JSF 2.1 might have the answer to your problem. Two new classes
> were introduced: FaceletCache and FaceletCacheFactory (see [1] and
> [2]). With a custom impl of those two you should be able to control
> the caching behavior!
>
> Regards,
> Jakob
>
> [1] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCache.html
> [2] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCacheFactory.html
Thanks for the answer ! Few hours after my question, by fortune I have
found this FaceletCache in JSF 2.1 implementation ;) I haven't chance to
test it yet, due to the fact that it was quite late, but it seems to be
promissing :)
I will report if it will going to work ;)
If someone is interested in our work, I can put here some information
and our consideration about application that we are creating (and info
about JSF and OSGi integration).
--
Pozdrawiam,
Kamil Soboń
iso.poczta(at)gmail.com
sobon(at)student.agh.edu.pl
Re: JSF + OSGi integration.
Posted by Jakob Korherr <ja...@gmail.com>.
Hi,
Nice stuff ;)
I think JSF 2.1 might have the answer to your problem. Two new classes
were introduced: FaceletCache and FaceletCacheFactory (see [1] and
[2]). With a custom impl of those two you should be able to control
the caching behavior!
Regards,
Jakob
[1] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCache.html
[2] http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/view/facelets/FaceletCacheFactory.html
2011/6/13 Kamil Soboń <is...@gmail.com>:
> Hi all,
>
> I don't know if I am writing in appropriate place, but assume that I am ;)
> So ... for some time, me and my friend are trying to create JSF application
> in OSGi environment.
> This application should be composed form core element and it's plug-ins.
> Each plug-in (OSGi bundle) can be install installed or uninstalled in
> run-time. Application should be aware of its plug-ins and its lifecycle
> (installing/uninstalling) without being restarted.
>
> To do so, we are combining few technologies: JSF (MyFaces) + PrimeFaces +
> Hibernate + Spring + OSGi (Equinox) + SpringDM (will be exchange to
> blueprint).
> To simplicy prototype we are going to use JSF + Spring + Spring-DM + OSGi
> only.
>
> As we have realized, JSF has not been planned to work with dynamic
> components (plug-ins) that can provide new views (xhtml pages), resources or
> manageable-beans. But specification of JSF allows to swap some application's
> modules/components.
> I have figure out some mechanism for providing views and resources
> (manageable beans is quite more complicated and it is not part of my
> question now :)) in run-time without violate JSF specification (in my
> opinion ofcourse :)).
>
> So our application is working in OSGi environment. The core is typical JSF
> application deployed to Tomcat (thanks to Spring-DM) which is also running
> in OSGi environment. Each plug-in is simply OSGi bundle that has dependency
> to Core. In Core there is PluginsResolverService that is responsible for
> detecting Core's available plug-in (assume that we are keeping Bundle
> descriptor).
>
> To provide views and resources in run-time (it is actuali working !) I have
> done 2 things:
>
> 1) I have implemented my own ExternalContext and ExternalContextFactory. Now
> we want to be aware of OSGi context not only about Servlet context, I have
> implemented:
> OsgiAwareExternalContextFactory which is quite simmilar to default
> implementation. There are 2 differences. This class in constructor requires
> ExternalContextFactory (decorator design pattern <- it is part of JSF
> specification). The second difference is that we thos factory provides
> OsgiAwareExternalContext that in constructor requires ExternalContext (which
> we can obtain from original ExternalContextFactory).
> OsgiAwareExternalContext (so far) delegates all of its method to original
> ExternalContext except of getResource(String) method. This method is using
> PluginsResolverService to obtain all plug-ins and to look if they are not
> containing resource that we are looking for.
> 2) I have implemented my own Servlet for handling non-faces request of
> resources.
>
> That is all. Now if i'am installing plug-in that provides view:
> someView.xhtml, I'am able to display it (I'am typing in web browser:
> {Context path of Core}/someView.xhtml). But there is one problem. JSF caches
> views. So if plug-in will be uninstalled, page someView.xhtml is still
> visible for users.
> I have found that DefaultFaceletFactory is responsible for caching views.
> And here is my question.
> If I want to provide my own FaceletFactory implementation I have to provide
> brand new implementarion of ViewDeclarationLanguageFactory !!!
>
> Standard implementation of ViewDeclarationLanguageFactory which is
> ViewDeclarationLanguageFactoryImpl creates in initialize() method
> FaceletViewDeclarationLanguageStrategy that is creating in constructor
> FaceletViewDeclarationLanguage that is creating in initialize() method
> FaceletFactory (DefaultFaceletFactory).
>
> FaceletViewDeclarationLanguage has protected method
> createFaceletFactory(FacesContext, Compiler) (wchich is called in
> initialize() method) that is responsible for creating FaceletFactory. But
> even it is protected method that I Can override I cannot provide my own
> implementation of ViewDeclarationLanguageBase (which will extends
> FaceletViewDeclarationLanguage) because there is no way of informing
> FaceletViewDeclarationLanguageStrategy thats should use my implementation.
> Shouldn't it be possible ?
>
> Sorry for my English :)
>
> --
> Pozdrawiam,
> Kamil Soboń
>
> iso.poczta(at)gmail.com
> sobon(at)student.agh.edu.pl
>
>
--
Jakob Korherr
blog: http://www.jakobk.com
twitter: http://twitter.com/jakobkorherr
work: http://www.irian.at