Experimenting a bit with the RESTXQ interface yesterday, using basexhttp I found that the default web.xml file shipped with BaseX 7.9 has an unfortunate property. The first servlet mapping listed is
<servlet-mapping> <servlet-name>RESTXQ</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
and the last servlet mapping is the default servlet, used for static data:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>
If I understand the Servlet specification correctly, this pattern of mappings ensures that a request for (say) a static resource will invariably be passed to the RESTXQ interface and not to RESTXQ.
Note that there is some doubt as to whether I do understand the spec correctly: on my reading, a request for /rest/ should also be passed to RESTXQ, and it's clearly not. But I was unable to get Jetty to serve any static content with the default web.xml. I began to succeed when I moved the servlet mappings and changed their patterns, along the lines of the web.xml file I found with Andy Bunce's GraphXQ example, so the first and last are:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> <!--* <url-pattern>/static/*</url-pattern> *--> </servlet-mapping>
<servlet-mapping> <servlet-name>RESTXQ</servlet-name> <url-pattern>/restxq/*</url-pattern> <!--* <url-pattern>/*</url-pattern> *--> </servlet-mapping>
There may be other ways to set the web.xml file up so that static resources are served (in particular, I don't think it's required to change "/static/*" to "/" -- but I have not experimented systematically with all options, because I'm interested in making my web application work, not in figuring out what relationship holds between the Servlet spec and Jetty's behavior.
Is this a problem others have run into? Is there a better solution?
And a related question -- before I changed the web.xml file (and after several unsuccessful changes), requests for any of
/test.xhtml /mydirectory/test.xhtml /static/test.xhtml /static/mydirectory/test.xhtml
elicited the response "Not found" (or sometimes "no function found"), but I found no entries for these requests in the BaseX logs. (And I was unsuccessful in attempting to turn Jetty's stderr or request logging on.)
Are failures of this kind not written to the BaseX logs?
If they aren't written to the BaseX logs, but would be written to Jetty logs, then I wonder if it would be helpful to have a few hints on turning Jetty logging on (and finding out where the log files get written) either in the BaseX documentation wiki or in comments in the default jetty.xml and web.xml. Since Jetty's documentation mostly assumes that its readers are Java programmers actively developing Java web apps, I for one found it unhelpful when trying to solve my problem.
Dear Michael,
Yes, RESTXQ is defined on top level in our web.xml file. Files that are located in the path of the default servlet won't be served by RESTXQ, but directly by the web server. The two remaining servlet mappings refer to REST and WebDAV, and both of them don't rely on RESTXQ either.
I must confess that our documentation [1] is not too verbose when it comes to the web.xml configuration; any contribution is more than welcome! Andy's XML configuration (which possibly stems from the web.xml file we used in the beginnings of RESTXQ) is exactly the way to go if you do not want to have RESTXQ on top level. As you correctly observed, there is no need to specify the default servlet if it points to the root path anyway.
any of ... elicited the response "Not found" (or sometimes "no function found"), but I found no entries for these requests in the BaseX logs. (And I was unsuccessful in attempting to turn Jetty's stderr or request logging on.)
If the message says "No function found", it means that there is no RESTXQ path defined for the supplied path. This info should be stored in the BaseX logs. In the other cases, the message was returned by the web server, so we have no control over it.
You are completely right, it would be helpful to activate Jetty's logging output in order to see what's going on. I have just added a new GitHub issue for your request [2]. There is also an older issue on logging [3]: We would like to redirect all BaseX logging output to a standardized logger, such as Log4J. It turned out that this is not as trivial as I hoped it would be, because BaseX provides so many different interfaces (CLI, GUI, Client/Server, HTTP), which all have different requirements.
Thanks for your feedback! Christian
[1] http://docs.basex.org/wiki/Web_Application [2] https://github.com/BaseXdb/basex/issues/1061 [3] https://github.com/BaseXdb/basex/issues/940
Michael,
As Christian suggests the web.xml from GraphXQ does date from the old default basexhttp configuration (~basex 7.8?). Initially I was unconvinced by the change to what is the current default configuration but I have grown to appreciate it.
This old configuration gives you a http server with a special path for RESTXQ. This is nice if you want to be able to just drop resources into the webapp folder and have them served like a web server does, with a small or maybe even no, RESTXQ component.
The current web.xml configuration gives you a RESTXQ server with a special path for static files (/static/*.html etc). In my applications I try to design them so that the static part could be easily moved to separate server. A potential source of confusion with RESTXQ is that the path specified in the annotation is unaffected by the physical file path of the RESTXQ file.
If you look at the dba code does not use /static at all but serves static files by reading them from the file system and using RESTXQ to server them. This allows better control of the headers for caching etc. but is more work.
The nice thing is that once you understand the web.xml configuration you can choose either style.
/Andy
On 22 January 2015 at 21:11, Christian Grün christian.gruen@gmail.com wrote:
Dear Michael,
Yes, RESTXQ is defined on top level in our web.xml file. Files that are located in the path of the default servlet won't be served by RESTXQ, but directly by the web server. The two remaining servlet mappings refer to REST and WebDAV, and both of them don't rely on RESTXQ either.
I must confess that our documentation [1] is not too verbose when it comes to the web.xml configuration; any contribution is more than welcome! Andy's XML configuration (which possibly stems from the web.xml file we used in the beginnings of RESTXQ) is exactly the way to go if you do not want to have RESTXQ on top level. As you correctly observed, there is no need to specify the default servlet if it points to the root path anyway.
any of ... elicited the response "Not found" (or sometimes "no function found"), but I found no entries for these requests in the BaseX logs. (And I was unsuccessful in attempting to turn Jetty's stderr or request logging on.)
If the message says "No function found", it means that there is no RESTXQ path defined for the supplied path. This info should be stored in the BaseX logs. In the other cases, the message was returned by the web server, so we have no control over it.
You are completely right, it would be helpful to activate Jetty's logging output in order to see what's going on. I have just added a new GitHub issue for your request [2]. There is also an older issue on logging [3]: We would like to redirect all BaseX logging output to a standardized logger, such as Log4J. It turned out that this is not as trivial as I hoped it would be, because BaseX provides so many different interfaces (CLI, GUI, Client/Server, HTTP), which all have different requirements.
Thanks for your feedback! Christian
[1] http://docs.basex.org/wiki/Web_Application [2] https://github.com/BaseXdb/basex/issues/1061 [3] https://github.com/BaseXdb/basex/issues/940
On Jan 23, 2015, at 3:27 AM, Andy Bunce wrote:
Michael,
As Christian suggests the web.xml from GraphXQ does date from the old default basexhttp configuration (~basex 7.8?). Initially I was unconvinced by the change to what is the current default configuration but I have grown to appreciate it.
I see the advantages of not having to start all RESTXQ requests with the string '/restxq/', and would prefer it. The more a URI exposes the mechanisms used by the implementation to handle the requests, the harder it is, later, to change the implementation without breaking the old URIs.
My difficulty was that I was unable to get the current default web.xml configuration to serve any static resources at all.
After a bit more experiment, I see now that part of my problem was a false analogy with the way the prefix patterns /rest/*, /restxq/*, and /webdav/* behave: they strip off the prefixes '/rest/', '/restxq/', or '/webdav/' and look for resources matching the remainder of the URI path. By analogy, I guessed that the default servlet, matching '/static/*', would strip off '/static/' and look for a resource (here a file in the file system) with a path that matches the remainder of the URI. It did not occur to me until this morning that Jetty (or the default servlet, or whoever is responsible) might not be stripping off the prefix, and instead might be looking for a directory named 'static' in the file system. I would prefer to avoid this for the same reasons I'd like to avoid having '/restxq/' in the URI. A fixed prefix is probably not too bad if there are directories which contain only static content, and if the static content is all contained in such directories.
My confusion was only exacerbated by the fact that the servlet spec says
The first successful match is used with no further matches attempted
which I misunderstood to mean 'first in textual order', making me wonder how, if the pattern /* is specified first, any other pattern is ever matched. Reading the passage again, in the light of the experiments I just did, makes me think it means 'first encountered in the algorithm not very clearly specified below'.
The nice thing is that once you understand the web.xml configuration you can choose either style.
Yes. I rather wish understanding the web.xml configuration file had not required quite so much of my time, or cost me quite so many gray hairs. But understanding it will be very useful, I hope. (Assuming that I do, finally, understand it correctly.)
Many thanks to both Christian and Andy for their help. If time permits, I hope to take up Christian's challenge and contribute some words on the web.xml configuration, for use in the documentation.
Hi Michael,
Many thanks to both Christian and Andy for their help. If time permits, I hope to take up Christian's challenge and contribute some words on the web.xml configuration, for use in the documentation.
;) Thanks as well for your observations; it will help me next time when I revise the relevant sections in our documentation.
Christian
If they aren't written to the BaseX logs, but would be written to Jetty logs, then I wonder if it would be helpful to have a few hints on turning Jetty logging on (and finding out where the log files get written) either in the BaseX documentation wiki or in comments in the default jetty.xml and web.xml.
I have now activated Jetty's logging output [1]. I think this change will simplify debugging in general , no matter if RESTXQ, REST, or WebDAV is used. As usual, a new snapshot is online.
Christian
basex-talk@mailman.uni-konstanz.de