: I was... then you talked me out of it! You are correct, the client : should determine the RequestParser independent of the RequestHandler.
Ah ... this is the one problem with high volume on an involved thread ... i'm sending replies to messages you write after you've already read other replies to other messages you sent and changed your mind :) : Are you suggesting there would be multiple servlets each with a : different methods to get the SolrParams from the url? How does the : servlet know if it can touch req.getParameter()? I'm suggesting that their *could* be multiple Servlets with multiple URL structures ... my worry is not that we need multiple options now, it's that i don't wnat to cope up with an API for writting plugins that then has to be throw out down the road when if we want/ened to change the URL : How would the default servlet fill up SolrParams? prior to calling RequestParser.preProcess, it would only access very limited parts of the HttpServletRequest -- the bare minimum it needs to pick a RequsetParser ... probably just the path, maybe the HTTP Headers -- but if we had a URL structure where we really wanted to specify the RequestParser in a URL param it could do it using getQueryString *after* calling RequestParser.preProcess the Servlet can access any part of the HttpServletRequest (because if the RequestParser wanted to use the raw POST InputStream it would have, and if it doesn't then it's fair game to let HttpServletRequest pull data out of it when the Servlet calls HttpServletRequest.getParameterMap() -- or any of the other HttpServletRequest methods to build up the SolrParams however it wants based on the URL structure it wants to use ... then RequestParser.process can use those SolrParams to get any other streams it may want and add them to the SolrRequest. Here's a more fleshed out version of the psuedo-java i posted earlier, with all of my adendums inlined and a few simple metho calls changed to try and make the purpose more clear... // Simple inteface for having a lazy refrence to something interface Pointer<T> { T get(); } interface RequestParser { public init(NamedList nl); // the usual /** will be passed the raw input stream from the * HttpServletRequest, ... as well as whatever other HttpServletRequest * header info we decide its important for the RequestParser to know * about the stream, and is safe for Servlets to access and make * available to the RequestParser (ie: HTTP method, content-type, * content-length, etc...) * * I'm using a NamedList instance instead of passing the * HttpServletRequest to maintain a good abstraction -- only the Serlet * know about HTTP, so if we ever want to write an RMI interface to Solr, * the same RequestParser plugins will still work ... in practice it * might be better to explicitly spell out every piece of info about * the stream we want to pass * * This is the method where a RequestParser which is going to use the * raw POST body to build up eithera single stream, or several streams * from a multi-part request has the info it needs to do so. */ public Iterable<ContentStream> preProcess(NamedList streamInfo, Pointer<InputStream> s); /** garunteed that the second arg will be the result from * a previous call to preProcess, and that that Iterable from * preProcess will not have been inspected or touched in anyway, nor * will any refrences to it be maintained after this call. * * this is the method where a RequestParser which is going to use * request params to open streams from local files, or remote URLs * can do so -- a particulararly ambitious RequestParser could use * both the raw POST data *and* remote files specified in params * because it has the choice of what to do with the * Iterable<ContentStream> it reutnred from the earlier preProcess call. */ public Iterable<ContentStream> process(SolrRequest request, Iterable<ContentStream> i); } class SolrUberServlet extends HttpServlet { // servlet specific method which does minimal inspection of // req to determine the parser name based on the URL private String pickRequestParser(HttpServletRequest req) { ... } // extracts just the most crucial info about the HTTP Stream from the // HttpServletRequest, so it can be passed to RequestParser.preProcss // must be careful not to use anything that might access the stream. private NamedLIst getStreamInfo(HttpServletRequest req) { ... } // builds the SolrParams for the request using servlet specific URL rules, // this method is free to use anything in the HttpServletRequest // because it won't be called untill after preProcess private SolrParams makeSolrRequestParams(HttpServletRequest req) { ... } public service(HttpServletRequest req, HttpServletResponse response) { SolrCore core = getCore(); Solr(Query)Response solrRsp = new Solr(Query)Response(); String p = pickRequestParser(req); // looks up a registered instance (from solrconfig.xml) // matching that name, similar to core.getQueryResponseWriter RequestParser solrParser = core.getParserByName(p); // let the parser preprocess the streams if it wants... Iterable<ContentStreams> s = solrParser.preprocess (getStreamIno(req), new Pointer<InputStream>() { InputStream get() { return req.getInputStream(); }); Solrparams params = makeSolrRequest(req); // let the parser decide what to do with the existing streams, // or provide new ones Iterable<ContentStreams> solrParser.process(solrReq, s); // ServletSolrRequest is a basic impl of SolrRequest SolrRequest solrReq = new ServletSolrRequest(params, s); // does exactly what it does now: picks the RequestHandler to // use based on the params in the solrReq, and calls it's // handleRequest method core.execute(solrReq, solrRsp); // the rest of this is cut/paste from the current SolrServlet. // use SolrParams to pick OutputWriter name, ask core for instance, // have that writer write the results. QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq); response.setContentType(responseWriter.getContentType(solrReq, solrRsp)); PrintWriter out = response.getWriter(); responseWriter.write(out, solrReq, solrRsp); } } -Hoss