[jetty-user] SPDY failures
Howard Lewis Ship <[email protected]> Wed, 6 Jun 2012 16:20:54 -0700
| Newsgroups | gmane.comp.java.jetty.support |
|---|---|
| Message-ID | <CACd-vsMz6o8HPe1Khe2qC002ZLzM70tZnsUxKndD=jRR7P-95g@mail.gmail.com> |
I'm attempting to set up a Tapestry 5 application on Jetty
8.1.4.v20120524, Mac OS X Lion, JDK 1.7, Chrome.
Most features work fine: HTTPs converts into SPDY (I'm using the SPDY
Indicator plugin for Chrome, and it turns green).
My page's HTML markup comes down fine, as does most of the related
images and stylesheets.
I'm having one problem though ... some of my larger JavaScript files
are coming through truncated. In production mode, Tapestry aggregates
many small JavaScript files into a single virtual file. This appears
to be failing, and I'm seeing exceptions on my server side, and
truncated JavaScript on the client side.
Here's some details:
EXCEPTION STACK:
org.apache.tapestry5.ioc.internal.OperationException
Protocol violation: cannot send a DATA frame on a closed stream
trace: Streaming asset stack en/core.js
java.lang.IllegalStateException
Protocol violation: cannot send a DATA frame on a closed stream
Stack trace:
- org.eclipse.jetty.spdy.StandardStream.data(StandardStream.java:393)
- org.eclipse.jetty.spdy.StandardStream.data(StandardStream.java:378)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection$HTTPSPDYGenerator.flush(ServerHTTPSPDYAsyncConnection.java:695)
- org.eclipse.jetty.server.HttpOutput.flush(HttpOutput.java:94)
- org.eclipse.jetty.server.AbstractHttpConnection$Output.flush(AbstractHttpConnection.java:1022)
- org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:173)
- org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:101)
- org.apache.tapestry5.internal.services.assets.BytestreamCache.writeTo(BytestreamCache.java:46)
- org.apache.tapestry5.internal.services.assets.StreamableResourceImpl.streamTo(StreamableResourceImpl.java:73)
- org.apache.tapestry5.internal.services.ResourceStreamerImpl.streamResource(ResourceStreamerImpl.java:145)
- $ResourceStreamer_12952a34919a54bc.streamResource(Unknown Source)
- org.apache.tapestry5.internal.services.assets.StackAssetRequestHandler$1.perform(StackAssetRequestHandler.java:105)
- org.apache.tapestry5.internal.TapestryInternalUtils$5.run(TapestryInternalUtils.java:582)
- org.apache.tapestry5.ioc.internal.OperationTrackerImpl$1.invoke(OperationTrackerImpl.java:51)
- org.apache.tapestry5.ioc.internal.OperationTrackerImpl$1.invoke(OperationTrackerImpl.java:48)
- org.apache.tapestry5.ioc.internal.OperationTrackerImpl.invoke(OperationTrackerImpl.java:74)
- org.apache.tapestry5.ioc.internal.OperationTrackerImpl.run(OperationTrackerImpl.java:47)
- org.apache.tapestry5.ioc.internal.PerThreadOperationTracker.run(PerThreadOperationTracker.java:76)
- org.apache.tapestry5.ioc.internal.RegistryImpl.run(RegistryImpl.java:1116)
- org.apache.tapestry5.internal.TapestryInternalUtils.performIO(TapestryInternalUtils.java:576)
- org.apache.tapestry5.internal.services.assets.StackAssetRequestHandler.handleAssetRequest(StackAssetRequestHandler.java:96)
- org.apache.tapestry5.internal.services.AssetDispatcher.dispatch(AssetDispatcher.java:114)
- $Dispatcher_12952a34919a54b4.dispatch(Unknown Source)
- $Dispatcher_12952a34919a54b9.dispatch(Unknown Source)
- $Dispatcher_12952a34919a54b2.dispatch(Unknown Source)
- org.apache.tapestry5.services.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:302)
- org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26)
- $RequestHandler_12952a34919a54b3.service(Unknown Source)
- org.apache.tapestry5.services.TapestryModule$3.service(TapestryModule.java:902)
- $RequestHandler_12952a34919a54b3.service(Unknown Source)
- org.apache.tapestry5.services.TapestryModule$2.service(TapestryModule.java:892)
- $RequestHandler_12952a34919a54b3.service(Unknown Source)
- org.apache.tapestry5.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:90)
- $RequestHandler_12952a34919a54b3.service(Unknown Source)
- $RequestHandler_12952a34919a54a7.service(Unknown Source)
- org.apache.tapestry5.services.TapestryModule$HttpServletRequestHandlerTerminator.service(TapestryModule.java:253)
- com.fivoosh.services.ajax.AjaxModule$1.service(AjaxModule.java:36)
- $HttpServletRequestHandler_12952a34919a54a9.service(Unknown Source)
- com.fivoosh.services.AppModule$12.service(AppModule.java:541)
- $HttpServletRequestHandler_12952a34919a54a9.service(Unknown Source)
- org.apache.tapestry5.internal.gzip.GZipFilter.service(GZipFilter.java:53)
- $HttpServletRequestHandler_12952a34919a54a9.service(Unknown Source)
- org.apache.tapestry5.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62)
- $HttpServletRequestFilter_12952a34919a54a2.service(Unknown Source)
- $HttpServletRequestHandler_12952a34919a54a9.service(Unknown Source)
- org.apache.tapestry5.services.TapestryModule$1.service(TapestryModule.java:852)
- $HttpServletRequestHandler_12952a34919a54a9.service(Unknown Source)
- $HttpServletRequestHandler_12952a34919a549f.service(Unknown Source)
- org.apache.tapestry5.TapestryFilter.doFilter(TapestryFilter.java:171)
- org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338)
- com.fivoosh.NakedDomainRedirectorFilter.doFilter(NakedDomainRedirectorFilter.java:33)
- org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338)
- org.eclipse.jetty.servlets.QoSFilter.doFilter(QoSFilter.java:205)
- org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338)
- org.eclipse.jetty.servlets.DoSFilter.doFilterChain(DoSFilter.java:479)
- org.eclipse.jetty.servlets.DoSFilter.doFilter(DoSFilter.java:327)
- org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338)
- org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:484)
- org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
- org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
- org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
- org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
- org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
- org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
- org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
- org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
- org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
- org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
- org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
- org.eclipse.jetty.server.Server.handle(Server.java:350)
- org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
- org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection.handle(ServerHTTPSPDYAsyncConnection.java:215)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection.performEndRequest(ServerHTTPSPDYAsyncConnection.java:371)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection.access$500(ServerHTTPSPDYAsyncConnection.java:61)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection$2.run(ServerHTTPSPDYAsyncConnection.java:301)
- org.eclipse.jetty.spdy.http.ServerHTTPSPDYAsyncConnection$1.run(ServerHTTPSPDYAsyncConnection.java:133)
- org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
- org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
- java.lang.Thread.run(Thread.java:722)
REQUEST:
Basic Information:
contextPath:
flags: secure
method: GET
path: /assets/20120528/stack/en/core.js
locale: en_US
serverName: localhost
Headers:
Accept: */*
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: max-age=0
Cookie: tapx-timezone=America/Boise;
JSESSIONID=ipnrrl4j225s103kx5r1mdqh9
Host: localhost
If-Modified-Since: Wed, 06 Jun 2012 22:48:48 GMT
Referer: https://localhost/login
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)
AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.53 Safari/536.5
scheme: https
I'm not sure where the flush() is coming from; here's the code for
BytestreamCache:
public class BytestreamCache
{
private final byte[] streamData;
public BytestreamCache(byte[] streamData)
{
this.streamData = streamData;
}
public BytestreamCache(ByteArrayOutputStream os)
{
this(os.toByteArray());
}
public void writeTo(OutputStream os) throws IOException
{
os.write(streamData, 0, streamData.length); // line 46
}
public int size()
{
return streamData.length;
}
public InputStream openStream()
{
return new ByteArrayInputStream(streamData);
}
}
Basically, the BytestreamCache captures the output of a
ByteArrayOutputStream (which itself contains the fully stream of
aggregated JavaScript, in UTF-8), and then can stream it to an
arbitrary OutputStream as needed.
It is likely that the BytestreamCache in this case has had its content
GZip compressed (Tapestry handles GZip compression itself, and caches
the result for later use). As a side note, I'm trying to figure out
how to identify SPDY requests from the HttpServletRequest API, as to
my understanding, SPDY handles compression itself.
In any case, I turned off GZip compression and didn't see a difference
here: I appeared to get the same exception on the same files,
regardless of whether GZip compression had occurred or not.
Tapestry will have set some response headers before opening the output
stream: it sets headers for Last-Modified, Expires, and
Content-Encoding (if the stream is compressed).
So, I'm at a loss. Much of the application appears to work correctly
with the SPDY support, but this is a critical area.
In terms of closing the stream ... when Tapestry renders a page, it
uses creates its own PrintWriter around the OutputStream from
HttpServletResponse.getOutputStream() ... after it finishes rendering,
it will close() that PrintWriter (which should propogate down to the
OutputStream). Should Tapestry be invoking flush(), not close()?
This occurs elsewhere as well ... that Tapestry will close() the
stream it obtains.
Thanks in advance for any help or insight. This is awfully bleeding edge stuff!
--
Howard M. Lewis Ship
Creator of Apache Tapestry
The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!
(971) 678-5210
http://howardlewisship.com
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email