users@grizzly.java.net

Re: Pointers for running Jersey services and serving static files.

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Fri, 30 Jan 2009 14:06:00 -0500

Salut,

Adrian Custer wrote:
> Hey all,
>
> Congratulations on the server---it has been a joy to find and use.
>
>
> In passing...
> The 'ServletAdaptor' javadocs are unintelligible---the intro paragraph
> could use a quick edit:
> https://grizzly.dev.java.net/nonav/apidocs/ ...
> ... com/sun/grizzly/http/servlet/ServletAdapter.html

OK will take a look :-) First pass I can see english is not perfect :-)


>
>
>
> If someone could point me towards the right strategy and docs for the
> following issue, I would appreciate the lead.
>
> We are building servers and have traditionally done this in a full scale
> container. (They are free software servers providing geospatial data,
> notably satellite imagery, according to ISO norms.)
>
> Recently, I started using Grizzly and got things working with the
> SelectorThread approach.
> SelectorThread t;
> try {
> t = GrizzlyWebContainerFactory.create(uri,
>
> GrizzlyWebContainerProperties);
> ...
> Now I'd like to add on the ability to serve some basic web pages at the
> root of the resource tree and, ideally, at the root of each context. For
> example, if we run our servers at the contexts:
> /wms
> /wcs
> /sos
> /csw
> I'd like a user who hits 'http://server:port/' to get a web page telling
> them a minimum of what is going on. That is, I'd like to have a simple
> web page for the / context. From Jean-Francois Arcand's blog, I see that
> a different approach to launching the server, 'new GrizzlyWebServer',
> allows one to combine servlets and static pages, but I don't quite see
> how to mix in Jersey based services. Are there any docs you could point
> me to?

GrizzlyWebServer is just a wrapper around SelectorThread to reduce the
complexity of interacting with SelectorThread long API. SelectorThread
was kept like that for backward compatibility, but we have added
GrizzlyWebServer to makes things much more trivial.

In order to serve static resources, you just need to invoke the
following method on the GrizzlyAdapter:

> https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/tcp/http11/GrizzlyAdapter.html#setHandleStaticResources(boolean)

You can configure the location of the static resources by invoking:

> https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/tcp/StaticResourcesAdapter.html#setRootFolder(java.lang.String)


>
> As an extra issue, I'd also like the user to get a service specific page
> if they hit one of the raw context roots, e.g. /wms .

So if I understand you correctly, you want to do some mapping like:

request = /wms --> mapped to --> resource X


All our services
> require url parameters to work so we are looking for parameters, e.g.
> ?request=GetCapabilities&service=wms&version=1.1.1
> to do any buisness logic.

Yes the Request/GrizzlyRequest offer such API to get those parameters:

> https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/tcp/http11/GrizzlyRequest.html#getParameter(java.lang.String)


or (more low level)

> https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/tcp/Request.html#getParameters()


I can readily get programatic control if the
> user doesn't send any parameters but I'm not sure then how to serve up a
> web page other than pure text, i.e. I don't understand how to provide
> access to images for the web page.

Can you elaborate a little? From my understanding, I would think if you
want to map a request to a file you need to do something similar to what
the StaticResourcesAdapter does:

https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/tcp/StaticResourcesAdapter.html
https://grizzly.dev.java.net/nonav/xref/com/sun/grizzly/tcp/StaticResourcesAdapter.html

e.g:

> // local file
> 170 File resource = cache.get(uri);
> 171 if (resource == null){
> 172 resource = new File(webDir, uri);
> 173 cache.put(uri,resource);
> 174 }
> 175
> 176 if (resource.isDirectory()) {
> 177 req.action( ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE , null);
> 178 res.setStatus(302);
> 179 res.setMessage("Moved Temporarily");
> 180 res.setHeader("Location", req.scheme() + "://"
> 181 + req.serverName() + ":" + req.getServerPort()
> 182 + "/index.html");
> 183 res.setHeader("Connection", "close");
> 184 res.setHeader("Cache-control", "private");
> 185 res.sendHeaders();
> 186 return;
> 187 }
> 188
> 189 if (!resource.exists()) {
> 190 if (logger.isLoggable(Level.FINE)){
> 191 logger.log(Level.FINE,"File not found " + resource);
> 192 }
> 193 res.setStatus(404);
> 194 if (commitErrorResponse){
> 195 customizedErrorPage(req,res);
> 196 }
> 197 return;
> 198 }
> 199 res.setStatus(200);
> 200
> 201 int dot=uri.lastIndexOf(".");
> 202 if( dot > 0 ) {
> 203 String ext=uri.substring(dot+1);
> 204 String ct= MimeType.get(ext);
> 205 if( ct!=null) {
> 206 res.setContentType(ct);
> 207 }
> 208 } else {
> 209 res.setContentType(MimeType.get("html"));
> 210 }
> 211
> 212 long length = resource.length();
> 213 res.setContentLengthLong(length);
> 214
> 215 // Send the header, and flush the bytes as we will now move to use
> 216 // send file.
> 217 res.sendHeaders();
> 218
> 219 fis = new FileInputStream(resource);
> 220 OutputBuffer outputBuffer = res.getOutputBuffer();
> 221
> 222 if (useSendFile &&
> 223 (outputBuffer instanceof FileOutputBuffer) &&
> 224 ((FileOutputBuffer) outputBuffer).isSupportFileSend()) {
> 225 res.flush();
> 226
> 227 long nWrite = 0;
> 228 while (nWrite < length) {
> 229 nWrite += ((FileOutputBuffer) outputBuffer).
> 230 sendFile(fis.getChannel(), nWrite, length - nWrite);
> 231 }
> 232 } else {
> 233 byte b[] = new byte[8192];
> 234 ByteChunk chunk = new ByteChunk();
> 235 int rd = 0;
> 236 while ((rd = fis.read(b)) > 0) {
> 237 chunk.setBytes(b, 0, rd);
> 238 res.doWrite(chunk);
> 239 }
> 240 }
> 241 } finally {
> 242 if (fis != null){
> 243 try{
> 244 fis.close();
> 245 } catch (IOException ex){}
> 246 }
> 247 }
> 248 }
> 249

Hope that help. Feel free to ask more questions :-)

A+

--Jeanfrancois


Once again, any pointers would be
> appreciated.
>
> Please respond directly to me since I am not on the list,
>
> thank you sincerely,
> --adrian custer
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>