Suppose the following application landscape:
+-----------------+
| App server |
+-----------------+
| | +-------+
| ear1 | | |
| +-web1 (/ctx1) +--<-- http://localhost/ctx1/xxx/ --+ +--<-- http://www.example.com/xxx/
| | | |
| | | proxy |
| ear2 | | |
| +-web2 (/ctx2) +--<-- http://localhost/ctx2/yyy/ --+ +--<-- http://abc.example.com/yyy/
| | | |
+-----------------+ +-------+
As you can see, proxy (nginx
in my case) is forwarding requests to to a single application server instance, which in turn has multiple web modules with different context paths. Of course I dont want my public server to expose internal context roots and proxy does it's job well, wraps and unwraps http requests, etc. But there is still one big problem: JSF-generated html code (links, css, js resources, form actions) contains context paths, /ctx1
and /ctx2
in my case. That's what I want to avoid.
I nave no solution at this moment of time except of using more and more different instances (domains) of application server, causing my hardware resources to fade away. As i understand it, I need to extend my JSF applications with some wrappers, potentially registered in faces-config.xml
, which would remove context prefix in generated html. Any other solutions are also welcome.
Please point me in the right direction.
I'm posting solution which may be helpful for others facing the same problem. All I needed to do is implementing my own javax.faces.application.ViewHandler
and register it in faces-config.xml
:
public class CustomViewHandler extends ViewHandlerWrapper {
private ViewHandler wrappped;
public CustomViewHandler(ViewHandler wrappped) {
super();
this.wrappped = wrappped;
}
@Override
public ViewHandler getWrapped() {
return wrappped;
}
@Override
public String getActionURL(FacesContext context, String viewId) {
String url = super.getActionURL(context, viewId);
return removeContextPath(context, url);
}
@Override
public String getRedirectURL(FacesContext context, String viewId, Map<String, List<String>> parameters, boolean includeViewParams) {
String url = super.getRedirectURL(context, viewId, parameters, includeViewParams);
return removeContextPath(context, url);
}
@Override
public String getResourceURL(FacesContext context, String path) {
String url = super.getResourceURL(context, path);
return removeContextPath(context, url);
}
private String removeContextPath(FacesContext context, String url) {
ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
String contextPath = servletContext.getContextPath();
if("".equals(contextPath)) return url; // root context path, nothing to remove
return url.startsWith(contextPath) ? url.substring(contextPath.length()) : url;
}
}
faces-config.xml :
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<view-handler>test.CustomViewHandler</view-handler>
</application>
</faces-config>