We’ve finally released 2.2! There’s a few features/changes I’d like to highlight here.
I’ll start with the fact that this release is not binary compatible with 2.1. Items to be aware of:
- CloseListener interface updated in order allow developers to distinguish between a local or remote close.
- Methods that accept CompletionHandlers no longer return Futures and methods that return Futures no longer accept CompletionHandlers. This was a fairly large change so I won’t go into which files were touched. While we understand this may be a point of frustration, we did reap some performance benefits and added API clarity from doing so. Please see revision 0d5f62 for details and how this may impact your project.
With the not-so-pleasant part out of the way, let’s talk about the fun stuff that’s been added.
Non-Blocking Sendfile Support
We now can support FileChannel.transferTo() to send files to a socket. This feature is available in the core framework and is easy to use. See the following for details:
- FileTransfer represents the intent to send a file via FileChannel.transferTo(). Simply create the instance, write it to the connection.
- FileTransferTest.java offers a concrete example of this feature.
We’ve also exposed this feature within the http-server module. Sendfile support will be enabled automatically if the underlying platform will support it properly. Sendfile support will be available if the underlying OS is not HP-UX or if the OS is Linux and the underlying JDK is 1.6.0_18 or newer. However, you can force the issue by enabling/disabling the feature via NetworkListener.setSendFileEnabled(boolean).
We’ve taken a page out of Tomcat’s playbook with how we’ve exposed this feature to developers. I’ll let the documentation explain…
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
/** * Request attribute will be associated with a boolean value indicating * whether or not it's possible to transfer a {@link java.io.File} using sendfile. * * @since 2.2 */ public static final String SEND_FILE_ENABLED_ATTR = "org.glassfish.grizzly.http.SEND_FILE_ENABLED"; /** * * The value of this request attribute, as set by the developer must be a {@link java.io.File} * that exists, is not a directory, and is readable. This {@link java.io.File} will be * transferred using sendfile if {@link #SEND_FILE_ENABLED_ATTR} is true. If sendfile * support isn't enabled, an IllegalStateException will be raised at runtime. * The {@link HttpHandler} using this functionality should refrain from writing content * via the response. * * Note that once this attribute is set, the sendfile process will begin. * * @since 2.2 */ public static final String SEND_FILE_ATTR = "org.glassfish.grizzly.http.SEND_FILE"; /** * The value of this request attribute signifies the starting offset of the file * transfer. If not specified, an offset of zero will be assumed. The type of * the value must be {@link Long}. * * NOTE: In order for this attribute to take effect, it must be * set before the {@link #SEND_FILE_ATTR} is set. * * @since 2.2 */ public static final String SEND_FILE_START_OFFSET_ATTR = "org.glassfish.grizzly.http.FILE_START_OFFSET"; /** * The value of this request attribute signifies the total number of bytes to * transfer. If not specified, the entire file will be transferred. * The type of the value must be {@link Long} * * NOTE: In order for this attribute to take effect, it must be * set before the {@link #SEND_FILE_ATTR} is set. * * @since 2.2 */ public static final String SEND_FILE_WRITE_LEN_ATTR = "org.glassfish.grizzly.http.FILE_WRITE_LEN"; |
So a typical example would look like:
|
1 2 3 4 5 6 7 8 9 10 |
@Override public void service(final Request request, Response response) throws Exception { if ((Boolean) request.getAttribute("org.glassfish.grizzly.http.SEND_FILE_ENABLED")) { request.setAttribute("org.glassfish.grizzly.http.SEND_FILE", new File(..)); } else { // your favorite byte-copy method goes here... } } |
Grizzly 2.2 Transport for Apache Thrift
Contributed by Bongjae Chang. Please see Bongjae’s blog entry on this topic for details.
RFC 6455: The Websocket Protocol
We’re up-to-date with respect to the Websocket RFC. We can somewhat back up this claim by stating 2.2 passes the Autobahn Websocket Server Test Suite. I’ll be sure to either post the results on our project page, or see if I can talk the Autobahn folks into including the results on their site as they do for Jetty.
Write I/O Thottling
We’ve added a new interface to allow throttling of write I/O to prevent overloading the async write queue and potential OOM situations
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * Callback handler, which will be called by Grizzly {@link org.glassfish.grizzly.Writer} * implementation, if message can not be neither written nor added to write queue * at the moment due to I/O or memory limitations. * User may perform one of the actions proposed by {@link PushBackContext} or * implement any other custom processing logic. * * @since 2.2 * * @author Alexey Stashok */ public interface PushBackHandler { /** * The method is invoked once message is accepted by * {@link org.glassfish.grizzly.Writer}. It means either message was written * or scheduled to be written asynchronously. * * @param connection {@link Connection} * @param message {@link WritableMessage} */ public void onAccept(Connection connection, WritableMessage message); /** * The method is invoked if message was refused by {@link org.glassfish.grizzly.Writer} * due to I/O or memory limitations. * At this point user can perform one of the actions proposed by {@link PushBackContext}, * or implement any custom processing logic. * * @param connection {@link Connection} * @param message {@link WritableMessage} * @param pushBackContext {@link PushBackContext} */ public void onPushBack(Connection connection, WritableMessage message, PushBackContext pushBackContext); } |
Our TunnelFilter.java sample shows this Interface in action.
Async HTTP Client
The next version of Async HTTP Client, 1.7.0, is close to being released. This will be the first release that offers a Grizzly-based provider (based on Grizzly 2.2). However, a new feature worth mentioning here is that this release will include WebSocket support! Again, taking advantage of the work by the Autobahn folks, we’ve run our WebSocket client implementation against their test suite and have passed. Once 1.7.0 goes final, I’ll create another blog entry with details!
Improved Performance
I touched on performance briefly when I covered binary compatibility. We’ll post some numbers in a follow up once we’ve been able to distill and generate some graphs.
I think that about covers it. The full change log for this release can be found here. Questions or concerns? Please feel free to contact us via the mailing lists!
I see, the class ServletHandler has been changed and cannot let me to add own Servlet instances and configure them from code.
Is there any possibility to have this functionality in 2.2?
Ah, right. I forgot to mention this in the binary compatibility section. I’ll be sure to update it. We did indeed make changes here to improve the API.
See BasicServletTest.java to get the basics of the new API. If you’re familiar with Servlet 3.0 at all, it should feel similar.
Thanks.
Pingback: Grizzly 2.2 release, open source Java NIO framework - Open News