Grzegorz Kossakowski skrev:
Daniel Fagerstrom napisaƂ(a):
Daniel Fagerstrom skrev:
Grzegorz Kossakowski wrote:
Hello,

I'm hacking now ajax and forms block to get them use of
servlet-services
and came across a bug. When you put ${cocoon.request.contextPath} into
JX template it will always return null (at least while using servlet
dispatcher). However, ${cocoon.request.requestURI} returns valid value,
so it must be only contextPath broken somehow. Unfortunately, I have no
skills to debug this.
Anyone can at least confirm this? Can you test it without servlet
dispatcher? (I would do it myself if I knew how)
I have not tested it. But looking at the code the servlet dispatcher
just embeds the request object from the servlet container with a
proxy. And the proxy doesn't affect the contextPath AFAICS, so it
might be that the context path is null in the original request.

For a servlet service that is called through the servlet protocol,
the contextPath will always be "", which is a bug. Currently the
request object of the calling servlet service is not available in the
servlet source, so there is no easy fix. I plan to refactor the call
stack and make it available there.

In the servlet architecture we have:

requestURI = contextPath + servletPath + pathInfo

As the servlet service architecture creates an extra level of paths
relative to the servlet architecture there are several possibilities
where to add the mountPath.  I solved it in the following way: the
dispatcher servlet will look for the mountPath that is the longest
prefix in the incoming pathInfo. It will then create a new
servletPath and pathInfo for the called servlet service:

newServletPath = servletPath + mountPath
newPathInfo = pathInfo.substring(mountPath.length())

So as you can see the contextPath will be the same as for all servlet
services.
Taking a look at your patches in JIRA I see that you have replaced
 {request:contextPath}/_cocoon/resources
with
 /blocks-test/cocoon-forms-impl/resources

Now the original pattern is actually faulty (even if it seem to be
used everywhere in the samples), it should have been
 {request:contextPath}{request:servletPath}/_cocoon/resources
and
 {request:contextPath}{request:servletPath}/resources
in your refactored code.

The only reason that the samples work is that the web.xml in
cocoon-webapp mounts the sitemap servlet at "/*" which gives
servletPath="", but there is no reason to constrain the use of the
sitemap servlet to be used only with an empty servlet path. A servlet
is supposed to be mountable wherever the user want it.

Using the servlet service fw, sitemap servlets will be mounted at
other paths and the servletPath must be taken into account.
Thanks for explanation. However, your proposed solution will not work.
In cocoon-ajax-sample we have:
<script type="text/javascript"
src="/blocks-test/cocoon-ajax-impl/resources/dojo/dojo.js"/>
Now if it is replaced by:
<script type="text/javascript"
src="${cocoon.request.contextPath}${cocoon.request.servletPath}/resources
/resources/dojo/dojo.js"/>
It would be resolved into:
<script type="text/javascript"
src="/blocks-test/cocoon-ajax-sample/resources/dojo/dojo.js"/>

So in short, all we want is '/blocks-test' part, the rest depends on
which block's resources we link to. How get this part?
You don't get that part, which show that there is a problem with my design. I probably mounted the dispatcher servlet at "/*" while developing the stuff :/ Thinking a little bit more about it, it would probably better to let the servlet path of the dispatcher servlet go to the context path when calling the servlet services. Then we would get:

newContextPath = contextPath + servletPath
newServletPath = mountPath
newPathInfo = pathInfo.substring(mountPath.length())

where servletPath above is the servletPath of the dispatcher servlet in the web.xml. Looking at it this mapping looks much more natural than the original one. But there might have been some god reason that I choose the original design that I have forgotten. If no one finds any problem with the new proposal we could switch to that.

To get the mountPath, it is better to use the blockPath module e.g. {block-path:ajax} (assuming that the cocoon-ajax-impl service servlet is connected at the name ajax in the Spring config). You can also use the service protocol inside the pipeline:

<script type="text/javascript"
src="servlet:ajax://resources/dojo/dojo.js"/>

and end the pipeline with a link rewriter transformer that use the block path module to get the path right.

The link rewriter transformer can probably be configured to add the prefix "/blocks-test" as well http://cocoon.apache.org/2.1/apidocs/org/apache/cocoon/transformation/LinkRewriterTransformer.html.

/Daniel

Reply via email to