Dashboard > Community Wiki > ... > Integration > Magnolia and JSF
Magnolia and JSF Log In View a printable version of the current page.

Added by GrĂ©gory Joseph , last edited by Boris Kraft on Jun 23, 2008  (view change)
Labels: 

As of now, this is more of a worklog than an actual how-to. Anyways, please update if you have experience with JSF.

JSF

I've been thinking about using JSF for handling the view tier here instead of plain JSP which normally is used by Magnolia. It has been done before by Rob Williams, Markus Strickler, Philipp Bracher and perhaps Ramon Buckland. Michael Aemisegger is also interested. Early this year, it seemed that the Magnolia team considered JSF to make out the MVC-architecture of Magnolia, but I'm not sure how that would work out since JSF is quite concentrated on the View-layer, and the original specs actually blackboxed the other parts of MVC to keep the spec within reasonable timeline.

Here are the pros:

  • Bean registry
  • Better architecture, seperating form-controllers from data-beans, session handling
  • Built in form validation, internationalization, localization
  • Some nifty view-component functions (sorting lists, javascripts, etc)

And some cons:

  • Complexity and steep learning curve of JSF
  • JSF-Magnolia integration gets tricky because Magnolia controls urls (Magnolia wants to virtualize all page URLs that it contributes content to, and since JSF has to set the destination URL in the form tag automatically, it means Magnolia gets cut out of the post back - Rob Williams)
  • JSF-Magnolia rsponsibilities overlap (not sure where, but I'm sure they do)

Here are some hints:

Phillip Bracher:
I think you'd have to set up separate mappings for magnolia servlet and
FacesServlet. And it might be tricky to mix JSF tags and magnolia tags. I have
never done it myself, though.

Rob Williams:
Running into a problem here:
1. Magnolia wants all page requests to be to virtual URLs.
2. JSF's form tag does not allow you to stipulate where the POST will go
to, so when it formulates the destination URL, it is to the actual page,
not the virtual one.

Boris Kraft:
Fabrizio has used Spring with Magnolia, might be intersting as well. On the other hand, our controls now seem to have matured quite a bit and are useful for Magnolia based projects. I imagine the Magnolia framework to move into the direction of a JSR-170 web application building framework.

Markus Strickler:
I've had some limited success in getting JSF and Magnolia work together.

What I did was add a paragraph that uses a .faces extension (mapped to the standard FacesServlet) and included that using cms:includeTemplate.
This worked OK with the only drawback that the form action pointed to the URL of the template instead of the enclosing page. I worked around that using some JavaScript, but there probably is a decent way to do this.
This way I got at least the guess example that comes with the standard implementation to work.
Then I decided to dig deeper into JSF before I continue...

Plan

Here's what I do:

  1. Read up on some JSF tutorial (I know JSF, just haven't used it in a while)
  2. Create a simple magnolia-module-webshop
  3. Try to use a simple JSF-tag in a simple Magnolia template
  4. Get the bean registry working
  5. Do a post from a template that appeals to a JSF action
  6. Get the JSF-action to redirect to another magnolia template (here it gets tricky)

Worklog

Mind that magnolia in its present state is not really good at shutting down the repo. Therefore, explicitly stop the context before restating tomcat.

  1. Installed magnolia from svn (I like berkelyDB).
  2. Deployed (make sure it is the only magnolia on the tomcat)
  3. Made a new template called calculator
  4. Got the JSP from Rick Hightiwer's tutorial

{{
Error: The absolute uri: http://java.sun.com/jsf/html cannot be resolved in either web.xml or the jar files deployed with this application
}}

Added jsf tld to WEB-INF (by adding jsf-impl.jar). Restarted context.

{{
Error: Entire Magnolia crashed (org.apache.jasper.JasperException at at info.magnolia.cms.servlets.EntryServlet.redirect(EntryServlet.java:214)
}}

Tried again copying both jsf-api.jar and jsf-impl.jar. Worked better. Now I get

{{
ERROR info.magnolia.cms.servlets.EntryServlet EntryServlet.java(doGet:144) 10.10.2005 20:21:10 Cannot find FacesContext
javax.servlet.ServletException: Cannot find FacesContext
}}

This is because I have not registered the FacesServlet probably.

Added this to web.xml:

{{
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 1 </load-on-startup>
</servlet>

<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>//magnolia/news/calculator-page.html</url-pattern>
</servlet-mapping>
}}

On saving web.xml, of course, tomcat restarted the context automatically. Still get the same error.

So now I tried adding faces-config.xml to WEB-INF...

Still got the same error.

Note that at this point, I've done excactly the things I had planned to do on introducing JSF to Magnolia, and I was quite sure it wouldn't work that easily. But at this point I have to invent some new options on what to do.

Full trace:

{{
2005-10-10 20:41:36 StandardContext[/magnolia]Servlet /magnolia threw load() exception
javax.servlet.ServletException: Servlet.init() for servlet Faces Servlet threw exception
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1071)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:862)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4013)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4357)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595)
at org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:277)
at org.apache.catalina.core.StandardHost.install(StandardHost.java:832)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:625)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:431)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:983)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:349)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1091)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:789)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1083)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:478)
at org.apache.catalina.core.StandardService.start(StandardService.java:480)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:2313)
at org.apache.catalina.startup.Catalina.start(Catalina.java:556)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:425)
----- Root Cause -----
java.lang.NullPointerException
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:144)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1029)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:862)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4013)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4357)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595)
at org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:277)
at org.apache.catalina.core.StandardHost.install(StandardHost.java:832)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:625)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:431)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:983)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:349)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1091)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:789)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1083)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:478)
at org.apache.catalina.core.StandardService.start(StandardService.java:480)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:2313)
at org.apache.catalina.startup.Catalina.start(Catalina.java:556)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:425)
}}

Found a possible solution:

The correction to this perplexing message was something I found in the jboss forums

The solution is to put the following in your web.xml file

{{
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
}}

(Note that somebody commented to that fellow that he should use myfaces)

This resulted in a

{{
java.lang.NoClassDefFoundError: org/apache/commons/digester/RuleSet
}}

So I got the commons digester and then I got

{{
java.lang.NoClassDefFoundError: org/apache/commons/beanutils/MethodUtils
}}

So I got the beanutils and then I got

{{
Configuration loaded!
}}

Whehey! Magnolia works again. But the calculator still won't load. Getting error trace:

{{
javax.servlet.jsp.JspException: Cannot find FacesContext
}}
At least it's a different error msg.

I'm guessing it's because I mapped Faces Servlet to /magnolia/news/calculator-page.html instead of /news/calculator-page.html

New error:

2005-10-10 21:03:32 ApplicationDispatcher\[/magnolia\] Servlet.service() for servlet jsp threw exception
java.lang.NullPointerException
	at org.apache.jsp.admintemplates.adminCentral.adminCentral_jsp._jspService(adminCentral_jsp.java:156)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:474)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:409)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
	at info.magnolia.cms.servlets.EntryServlet.redirect(EntryServlet.java:214)
	at info.magnolia.cms.servlets.EntryServlet.doGet(EntryServlet.java:126)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:474)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:409)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
	at info.magnolia.cms.servlets.EntryServlet.redirect(EntryServlet.java:214)
	at info.magnolia.cms.servlets.EntryServlet.doGet(EntryServlet.java:126)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at info.magnolia.cms.security.SecurityFilter.doFilter(SecurityFilter.java:68)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at info.magnolia.cms.filters.MultipartRequestFilter.doFilter(MultipartRequestFilter.java:80)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at info.magnolia.cms.filters.ContentTypeFilter.doFilter(ContentTypeFilter.java:65)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
	at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
	at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
	at java.lang.Thread.run(Thread.java:595)

This is a very common error when messing around with the servlets. Problem is that magnolia servlet does not load, and adminCentral.jsp can not get the user out of session. Note that when you get this error, you often have to restart the entire tomcat for magnolia to work again (a simple restart context gave me NPEs).

Just for fun before I go, I try mapping /news/* to the FacesServlet.

Now, for the first time I am getting what I actually should be getting: a 404 - the resource does not exist. This is clear because if the magnolia servlet does not load this page for me (generating the page) - there is no content using my calculator template. Lesson learned is that both servlets need to paint the result of this thingie. Will continue in the morning.

Todo:

  1. Find out if out how the servlets will work together, if possible at all
  2. Try to use myFaces instead (since it is just better)
  3. Perhaps the only solution is to have static jsf's lying in docroot.

Day two

Trying to implement Markus' suggestion: Having JSF-paragraphs.

Turned my calculator.jsp from a JSF-page into a regular Magnolia template like templateTwoColumns.

Made a new paragraph template called calculatorParagraph.jsf. Put the old content of calculator (JSF-tags) inside this one. Turned into JSP Document.

Tried mapping the FacesServlet to *.jsf, but this contiously broke magnolia. Suddenly my website repostory even disappeared

I'm not actually doing what Markus was doing, if I have understood him correctly. He didn't create one jsf-paragraph, rather he included one jsf-page in his template, which is not the same.

Didn't get to try out too much stuff today. Will see tomorrow. If things keep going rusty like this, I'll might give up.

Day three

Today I will look closer on the Magnolia Servlet.

I turn off caching, to avoid those NPE's (or rather getting them excactly when I should). Silly that I didn't think of that sooner.

Installed a fresh magnolia. Will try to edit the existing sample templates instead of making new ones.

I'm still getting those tricky NPE's. Tried restarting tomcat. Didn't help.

Getting an java.lang.IllegalStateException: Cannot forward after response has been committed

Typical error when the servlets are messed up. Perhaps svn is broken.

Removed Magnolia again. Deployed 2.1 release instead.

Editing templateOneColumn. Including a jsf file - calculator.jsf with no actual jsf inside.

Each time I try to access the page, the tomcat leaps out of memory control. There's a unlimited loop called here for some reason:

javax.servlet.ServletException: javax.servlet.jsp.JspException: null
	at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:821)
	at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:758)
	at org.apache.jsp.templates.jsp.samples.templateOneColumn.main_jsp._jspService(main_jsp.java:94)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:474)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:409)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
	at info.magnolia.cms.Dispatcher.dispatch(Dispatcher.java:79)
	at info.magnolia.cms.servlets.EntryServlet.doGet(EntryServlet.java:141)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
	at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:590)
	at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:510)


...loops and loops

I rename calculator.jsf to calculator.jsp and it works (is included properly).

Situtation now is that if I try to rename it to jsf, I get an endless looping getAttribute from somewhere.

I tried adding jsf to the Magnolia MIMEMapping. Didn't help.

Trying to include anything other than a file with a .jsp ending causes tomcat to crash.

Tried using the jsf file indirectly with cms:includeTemplate results just leads to a NPE: no content node found.

Try changing source jsp for one paragraph type (table) to the jsf file (templates/jsp/paragraphs/table.jsf). Didn't work. Endless loop.

Giving up! Garrrr..

Other known authors include :

  • PlanetPratt
  • Ferris
Powered by a free Atlassian Confluence Open Source Project License granted to Magnolia International. Evaluate Confluence today.
Powered by Atlassian Confluence 2.7, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators