Is there an easy way to implement routing in JSF?

I am trying to implement a โ€œgeneralโ€ view where (part) of the displayed content is dependent on the URL. For instance.

If /somepath/somepage.xhtml points to a non-existent file, instead of going straight to 404 error, I want to try to extract the contents of /somepath/somepage.xhtml from the database using the general view /genericview.xhtml , where I have that something like:

 <h:outputText value="#{genericViewBean.content_lg}" escape="false" /> 

which, if found under the bean, will display the contents of the database record from the tgenericcontent table, depending on the originally requested viewId:

  webpath | content /somepath/somepage.xhtml | <p>This is a test</p> /someotherpath/someotherpage.xhtml | <p>A different test</p> 

If the contents of the view are not found in this table, then standard 404 error will be returned.

The closest I got to clone /genericview.xhtml , changing only the path to the file (for example, to /somepath/somepage.xhtml ). But it gives me one exact copy of the file for each view, it is pretty messy and it doesnโ€™t allow me to create a new URL just by adding an entry to my database.

How to get the same result without cloning /genericview.xhtml ?

(PS: I read about surfaces, but is there a simpler solution?)

+5
source share
1 answer

A servlet filter is usually used for this. PrettyFaces , UrlRewriteFilter, and FacesViews also do it this way.

You can get the request URI of HttpServletRequest#getRequestURI() . You can check for the ServletContext#getResource() web resource, which will return null on non-existent resources. If the resource exists, simply continue with the FilterChain#doFilter() request, otherwise forward the request to the general form RequestDispatcher#forward() .

In general, the filter looks like this:

 @WebFilter("/*") public class GenericViewFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String relativeRequestURI = request.getRequestURI().substring(request.getContextPath().length()); boolean resourceExists = request.getServletContext().getResource(relativeRequestURI) != null; boolean facesResourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)); if (resourceExists || facesResourceRequest) { chain.doFilter(request, response); } else { request.getRequestDispatcher("/genericview.xhtml").forward(request, response); } } // ... } 

In /genericview.xhtml original URI request is available as a request attribute with RequestDispatcher#FORWARD_REQUEST_URI . You can use it in @PostConstruct to support beans associated with the view in order to pull the correct content from the database.

 String originalRequestURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI); // ... 
+9
source

Source: https://habr.com/ru/post/1210915/


All Articles