Forums de discussion

JSF/Primefaces custom components and portlet question.

Lisa Dupont, modifié il y a 10 années.

JSF/Primefaces custom components and portlet question.

New Member Publications: 14 Date d'inscription: 01/08/13 Publications récentes
Hello,

I have custom JSF 2/Primefaces 3.5 components that I would like to use in several liferay portlets.
The custom components are composed of 2 files : my_custom.xhtml and my_custom.java.
In my_custom.java, my_custom extends UINamingContainer.

I created a .jar to put the sources for the custom components.
As I don't want to have to put this jar in all my portlet's WEB_INF/lib directories (It also contains some other application initialization code like database connection...),
I put it in the Liferay_install/tomcat/lib/ext directory. So that the sources of the custom components in it can be common to all portlets.

Putting MyApp_and_JSF_custom_components.jar in Liferay_install/tomcat/lib/ext forced me to also put jsf-api-2.1.3.jar and primefaces3.5.jar in the same directory
(they are needed by the MyApp_and_JSF_custom_components.jar).

But, as my portlets (those who use the custom components in the jar) are deployed, I get an error at startup.

It says:

GRAVE: Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) com.sun.faces.config.ConfigureListener
java.lang.RuntimeException: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.context.PartialViewContextFactory' was not configured properly.
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:292)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:895)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1099)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1621)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.context.PartialViewContextFactory' was not configured properly.
at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:305)
at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:219)
at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:360)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:225)
... 14 more
Caused by: javax.faces.FacesException: org.primefaces.context.PrimePartialViewContextFactory
at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:616)
at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:482)
at javax.faces.FactoryFinder.access$400(FactoryFinder.java:138)
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:949)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:316)
at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:303)
... 17 more
Caused by: java.lang.InstantiationException: org.primefaces.context.PrimePartialViewContextFactory
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:614)
... 22 more

Anyway, I was wondering if my idea of putting JSF/primefaces custom components in a jar in liferay_install/tomcat/lib/ext is any good.
Liferay uses bridge classes so that JSF portlets can run in the portal.
The bridge classes are in the portlet's WEB_INF/lib directory.
Is there any chance to be able to use the custom components in portlets if primefaces.jar and jsf-api.jar classes are loaded before the bridge classes?
Any suggestion as to where my custom components should be placed?

Any help is welcome.
thumbnail
Neil Griffin, modifié il y a 10 années.

RE: JSF/Primefaces custom components and portlet question.

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Hi Lisa,

I was able to reproduce the issue you reported by doing this:

tomcat/lib/ext/jsf-api.jar
tomcat/lib/ext/primefaces.jar
tomcat/webapps/foo-portlet/WEB-INF/lib/jsf-impl.jar
tomcat/webapps/bar-portlet/WEB-INF/lib/jsf-impl.jar

But when I moved jsf-impl.jar to tomcat/lib/ext and did not include jsf-impl.jar within each portlet, everything worked fine.

Kind Regards,

Neil
Lisa Dupont, modifié il y a 10 années.

RE: JSF/Primefaces custom components and portlet question.

New Member Publications: 14 Date d'inscription: 01/08/13 Publications récentes
Thank you very much Neil,
It works now.Yet, I now have another problem. Maybe I will have to change my portlet and my application design because of that but, I prefer to ask first.

The problem is the following :
In my_app.jar, I have a MyCustomComponent.class that is the source code for MyCustomComponent.xhtml that I use in my portlet's view.xhtml.
MyCustomComponent.xhtml has an an attribute (heres's the view.xhtml line):

<view:MyCustomComponent id="aa" myCustomAttrib="portlet_sources.MyClassInPortletSourceCode">

So, in MyCustomComponent.class, I have a setMyCustomAttrib method that tries to instantiate a portlet_sources.MyClassInPortletSourceCode object.
setMyCustomAttrib is called when I request the page on which I put the portlet.

I get a java.lang.ClassNotFoundException then.

I suppose that this is dued to the fact that classes in jars in Liferay_install/Tomcat/lib/ext are loaded first and by a different class loader then classes
that are defined in the deployed JSF portlet.

Is there any way for the code in my_app.jar to know about a class defined in the portlet?
thumbnail
Neil Griffin, modifié il y a 10 années.

RE: JSF/Primefaces custom components and portlet question.

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Your setMyCustomAttrib method might be able to call the invoke method in PortletClassInvoker in order to make it work. I would recommend that you take a look at the source for PortletClassInvoker.java to give you more ideas.