Direct JSP Servlet

A lot of Liferay TagLibs use including JSP files to present their content.

Is there any difference between TagLib used JSPs and the normal ones?
Functionally, they are the same thing.
But when we see them from performance view, there is a huge difference.

Whenever we do a jsp include, there are two major performance related steps:
 

  • 1) Jsp servlet looking up.

Code example:
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);

The ServletContext.getRequestDispatcher(String path) is a heavy app-server api call, which needs to look up app-server's jsp servlet resource.

  • 2) Filter Stack setting up and traversing

Code example:
requestDispatcher.include(request, response);

No matter you want it or not, the invocation will set up the filter stack(by request URL regex pattern mapping), and traverse all the filters in the stack one by one.

For a normal jsp including, there is nothing wrong with these two steps. But for TagLib, things are a little different, And this little difference can bring us huge performance improvement.

For 1) in general cases, path parameter is various, there is a large candidate pool.
But for TagLibs, the candidate pool is relatively smaller, which means we can consider to cache the path mapping to the underneath JSP servlet. This can save us the look up time significantly.

For 2) in general cases, filters are absolutely needed.
But for all Liferay TagLibs, filters are guaranteed not needed. So the setting up and traversing filters are huge performance waste, we should call the JSP servlet directly without bothering the filters.

In LPS-13776, I made an improvement based on these analyzing.
I added a cache to hold path to servlet mapping, so the looking up will only happen once when the jsp is included for the first time. After that all looking up hit the cache.
By using the DirectRequestDispatcher, all include calls is sent directly to the jsp servlet without any filter processing.

You can turn on this feature by setting:
direct.servlet.context.enabled=true
By default this is on.

One drawback about the mapping cache is losing jsp dynamic reloading ability at runtime, which is not acceptable for developers. To overcome this pitfall, I added a timestamp to the mapped jsp servlet, whenever receives a request for a jsp servlet, it will check the jsp file's timestamp, compare to the jsp servlet's timestamp. If the external jsp file is newer, do a reload. This reloading is only required at development time, on production server it is totally a waste.
You can turn off this feature by setting:
direct.servlet.context.reload=false
By default this is on.

博客
So it's better to be added it to portal-developer.properties, right?

direct.servlet.context.reload=false
No, it should be direct.servlet.context.reload=true for development.
direct.servlet.context.reload=false for production.

By default it is on for developers' convenience, when going production, you should turn if off in portal-ext.properties
Very Nice blog for productions performance enhancement!!!