OpenNTF / org.openntf.xsp.jakartaee

XPages Jakarta EE support libraries
Apache License 2.0
21 stars 7 forks source link

Investigate using XPages as view engines in MVC #127

Open jesse-gallagher opened 2 years ago

jesse-gallagher commented 2 years ago

It should be possible to do much the same thing that the existing ServletViewEngine implementations do, rewriting the URL to match an incoming XPage. This should also work with partial refreshes, since those URLs are built relative to the server.

jesse-gallagher commented 2 years ago

On first swing, this has proven oddly fiddly. Though I wrap the incoming request in a way that should look like a clean incoming XPage request, the runtime nonetheless complains that it can't find the class xsp.xsp.App, indicating that it's trying to use /xsp/app as the incoming page ID.

It's possible that I'm missing some entrypoint I can set, but it's also possible that the stack fetches the true incoming request from elsewhere. NotesContext stashes the request, but I don't think it makes it available to callers. Still, something along those lines would cause this behavior.

jesse-gallagher commented 2 years ago

Part of the proximate trouble is the code in FacesServletEx#serviceAjaxPartialView that determines the view ID. It gets the request from the param FacesContext#getExternalContext(), and that's the true underlying request - not the one we pass in.

jesse-gallagher commented 2 years ago

That must happen somewhere in this part of the stack:

    com.ibm.xsp.webapp.FacesServletEx.serviceAjaxPartialView(FacesServletEx.java:200)
    com.ibm.xsp.webapp.FacesServletEx.serviceAjaxPartialViewSync(FacesServletEx.java:169)
    com.ibm.xsp.webapp.FacesServletEx.serviceView(FacesServletEx.java:155)
    com.ibm.xsp.webapp.FacesServlet.service(FacesServlet.java:163)
    com.ibm.xsp.webapp.FacesServletEx.service(FacesServletEx.java:138)
    com.ibm.xsp.webapp.DesignerFacesServlet.service(DesignerFacesServlet.java:103)
    org.openntf.xsp.mvc.impl.XspViewEngine.processView(XspViewEngine.java:98)

What we pass in from XspViewEngine is a local anonymous class, wrapped in the new wrapper from ServletUtil.

jesse-gallagher commented 2 years ago

The trouble is clear in retrospect: by the time XspViewEngine is involved, there's already a FacesContext registered based on the original incoming request - and FacesControllerImpl uses that when present.

jesse-gallagher commented 2 years ago

While it may be possible to temporarily un-set FacesContext during the MVC request, it's more complicated than just calling the setCurrentInstance method from a subclass - that just moves on to an NPE when it comes to the ApplicationEx instance.

So this could still be doable as it is, but it may be better to tie it to https://github.com/OpenNTF/org.openntf.xsp.jakartaee/issues/140