Category: Jakarta

  • Java Updates, Jetty, and the Future

    There has been a tremendous amount of information, and a fair amount of disinformation, coming out over the last several months with regards to Java versioning, the effects of modularization, and how projects like Jetty may or may not respond to them. In light of that, we wanted to more comprehensively explain what we have seen thus far, where things are going, and what we are planning to do with Jetty. We are also interested in any feedback from our clients as to what their expectations might be as well as any trials and tribulations you might be having.
    With that in mind, here we go!

    Oracle’s new JDK Release Schedule

    Oracle has published an updated JDK release schedule.
    Oracle will make JDK 8 updates for critical bugs or security fixes publicly available until January 2019. After that, you need to purchase Oracle support for the JDK if you want to continue to use JDK 8 and receive the latest bugs and security fixes.
    As part of their revamped Support Roadmap, Oracle has introduced the term “Long Term Support” for certain JDK releases. However, the term may be confusing, as it practically refers only to customers that purchase Oracle support for the JDK.
    Therefore, if you don’t purchase Oracle support for the JDK, then:

    • JDK 8 will be updated up to January 2019; after that, the supported JDK version will be JDK 11.
    • JDK 9 will not be updated.
    • JDK 10 will be updated up to September 2018; after that, the supported JDK version will be JDK 11.
    • JDK 11 will be updated up to March 2019; after that, the supported JDK version will be JDK 12.
    • JDK 12 will be updated up to September 2019; after that, the supported JDK version will be JDK 13.
    • And so on.

    In different words, those that did not purchase Oracle support for the JDK will have “Long Term Support” by moving to a new JDK version every 6 months.
    Alternatively, it is possible to stay on JDK 11 for more than 6 months by purchasing Oracle support for the JDK, as outlined in the JDK release schedule linked above.

    Oracle’s JavaFX Support

    Oracle’s JavaFX support is outlined in this blog post.
    JavaFX was previously bundled with the JDK, but starting in JDK 11 this will no longer be the case, and JavaFX will be available as a separate download.

    Jetty and JDK versions

    Jetty 9.4.x will be supported on publicly available releases of the JDK from JDK 8 or later. However, we strongly encourage Jetty users to keep pace with JDK releases, to benefit from critical bug fixes, security fixes and new features. At the time of writing Jetty 9.4.x already builds and runs on JDK 8, JDK 9, JDK 10 and early access builds of JDK 11.
    JDK 11 will remove classes previously available in the JDK, as detailed in this issue on GitHub. Jetty does not need those classes, but often applications do.
    Standalone Jetty users will have the choice of either adding the jars containing those classes to their applications (for example in the WEB-INF/lib directory of a web application) or to write a custom Jetty module that exposes those classes to all web applications deployed to Jetty.
    Embedded Jetty users will need to add the jars containing those classes to the classpath.
    If you have questions as to what jars are available for your specific need that may be removed we encourage you to reach out to us early!

    Recommended JDK version migration plan

    We strongly recommend to start planning an upgrade to a JDK version greater than 8 (at this time, JDK 10) right nowMoving from JDK 8 to JDK 11 in September 2018, when JDK 11 will be out, will likely be a too big of a change and too risky.
    In particular, the update from JDK 8 to JDK 9 resulted in a possibly large number of incompatibilities, among which include:

    • Removal of tools.jar
    • Removal of JavaDB
    • Removal of the endorsed directory mechanism
    • Removal of the extension directory mechanism
    • Classloading implementation changes
    • A new Java version string scheme – leads to issues when parsing the Java version string
    • Removal of non-critical internal APIs – for example sun.misc.Base64Decoder
    • URLStreamHandler mechanism changes
    • Removal of many (50+) JVM startup options – the JVM refuses to start if a removed option is specified on the command line
    • New format for the JVM logging – big impact on GC logging

    The main problem is that many of these issues may impact your application and all the libraries your application depends on. Your application may not perform classloading, or lookup the system property “java.version”, but the libraries your application depends on may do so. Most of the issues listed above will only manifest at runtime, perhaps while executing an if statement branch that may only be entered under rare conditions.
    The changes listed above impact not only the development of your applications but also their build and their deployment. In some cases, development and deployment are the responsibility of different departments throughout a company, and it may take time to coordinate the changes.
    The best approach for the development side is to update both your build tools (for example, Maven and Maven Plugins) and your library dependencies to their latest versions.
    After that, it is a process of trial and error to make sure that your application works correctly in every possible scenario. A good test suite helps tremendously in this case, as you will be able to test most if not all of your code.
    The update from JDK 9 to JDK 10 should instead be really smooth, typically just a matter of updating the JDK: if your application works in JDK 9, most probably will work in JDK 10 without changes. The update from JDK 10 to JDK 11 may again have issues because of the classes removed from JDK 11, as discussed above.
    In light of the large number of changes that happened with JDK 9, and considering that the changes may affect your application and the libraries your application depends on (which you may need to update, or ask their maintainers to update), and further considering that the changes affect the build, development and the deployment of your applications, we strongly suggest that you start planning for these changes right now, as putting it off any longer may be too late. If you cannot finish the migration from JDK 8 to JDK 11 by January 2019, you risk running on an outdated JDK 8 release that may contain critical bugs or security issues.

    JDK Vendors

    Since OpenJDK is an open source project, many vendors have licensed the Java Test Compatibility Kit (TCK) and will produce OpenJDK builds that have passed the TCK and therefore are suitable for production use.
    Among these vendors there are:

    These vendors, excluding LJC, will offer free OpenJDK builds that are TCK-tested for the current JDK version and commercial support for previous JDK versions.
    Azul System has nicely summarized both Oracle’s and their own support plans for JDK 8 through JDK 19 in the graphs at this page.
    LJC is providing free OpenJDK builds that are TCK-tested at this page: https://adoptopenjdk.net/LJC “support” is just to build and TCK-test the tags of the OpenJDK project.
    For example:
    You decide to use JDK 9; the current version is JDK 10; a JDK security issue is discovered. Then:

    • The issue will be fixed in the OpenJDK 10 project and a new OpenJDK 10 tag will be created.
    • Oracle will issue a new micro version of JDK 10 (e.g. 10.0.2).
    • LJC will provide an OpenJDK 10 build for the newly created OpenJDK 10 tag.
    • If the issue is backported to OpenJDK 9 (and a new OpenJDK 9 tag created), then:
      • Oracle will not provide any support (will ask you to move to JDK 10.0.2)
      • Azul will provide a JDK 9 build, but only to its paying customers
      • LJC should provide a free OpenJDK 9 build for the newly created OpenJDK 9 tag.

    JakartaEE and JavaEE

    In addition to the efforts by Oracle to plot a more rapid release environment for the JDK, they have donated the entire JavaEE platform to the Eclipse Foundation. JavaEE has been subsequently rebranded as JakartaEE and is currently under the process of being migrated and re-released with the same version number. That is JavaEE 8 will be released as JakartaEE 8 once that migration process has been completed. One interesting note is there is as this point no API changes nor functionality changes for JakartaEE 8 which will carry with it the same minimal JDK 8 version.
    A point of interest, Webtide has members who are serving as co-leads on both the Servlet and Websocket specifications as well as Architecture Council representation within the Foundation itself.

    What everything means!

    The Jetty team has already, and will continue to, do the work of migrating and making sure the Jetty code base is compatible with the most up-to-date JDK versions. In addition, we will endeavor to support the minimal version of JDK that is required for the forthcoming JakartaEE specifications. As new JDK versions are released, we are constantly updating and reviewing them to guarantee Jetty remains stable and ready for consumption.
    This means that for now, it is our intention to support JDK 8, 9, 10, and 11 for Jetty 9.4.x releases. We have yet to begin Jetty 10.0.x releases due in large part to the upheaval associated with the JakartaEE code donation coupled with this relatively new accelerated JDK release schedule. We anticipate a different approach to new Jetty 10.0.x releases as they relate to JDK releases but nothing is set in stone in this regard. One approach may be to support the minimal version required by the JakartaEE version and the most current two JDK releases. It seems an untenable situation to pledge support for a minimal version like JDK 8 and every version of the JDK between official LTS versions (JDK 11 through JDK 17!).
    Regardless, we are always available to assist our clients with any questions or migration issues may come across related to this situation. If you have internal plans for how you intend to update JDK versions in the future or expectations on how Jetty will interact with future JDK releases we encourage you to share with us to help manage expectations.

  • Getting Started with Jetty and JDK 9

    It’s finally here! Java 9 has officially been released and includes a whole host of changes and new functionality. Jetty, too, has been built with Java 9 over the past few releases as we ramp up support for the new JDK. It’s important to note that while Jetty is being built with Java 9, it currently does not support the entire suite of changes that came with it. To be clear – Jetty does not currently support Java 9 modules.
    Being that JDK 9 is still so new, Jetty’s support for it is still evolving. As such, it is imperative that users wishing to get the most out of JDK 9 and Jetty remain up-to-date as releases become available. Below is a summary of common problem areas that Jetty has resolved in the most recent releases.

    Annotation scanning

    Prior to Jetty 9.4.7,  multi-release jar files will produce exceptions trying to scan “module-info.class” for annotations. It will also not scan a multi-release jar for the correct versions of classes (i.e. Jetty will scan everything in the root and also everything in META-INF/versions).
    If any of your 3rd party jars (multi-release or not) use Java 9 APIs, then you will need to use Jetty 9.4.8 to get the updated version of ASM capable of parsing those classes.

    Classpath issues

    Pertinent only to embedded uses, prior to Jetty 9.4.8 Jetty was unable to find jars to scan for annotations, or for META-INF information such as web-fragments, resources and tag libs from the container classpath when running with Java 9. This did not apply to executing Jetty via the distribution or via the Jetty Maven Plugin.

    Compilation

    Since Jetty 9.4.7, JDK 9 is used to build Jetty (although it can still be built using JDK 8).
    JDK 9 incorporates a new switch in the javac compiler (–release) that allows to easily compile against previous JDK versions, as defined by JEP 247.
    This new compiler switch is supported by the Maven Compiler Plugin, and we use it while building Jetty with JDK 9, with the configuration –release=8, which allows Jetty to run in JDK 8.
    Only few modules (namely those that use new JDK 9 APIs, such as the jetty-alpn-java-[client|server] modules) are compiled with –release=9.
    With this compiler configuration it is less likely that usages of JDK 9 classes and/or APIs can accidentally slip into modules that are meant to be JDK 8 compliant.

    ALPN Support

    Jetty 9.4.6 only supports ALPN via the alpn-boot mechanism, which requires the alpn-boot jar to be in the bootclasspath.
    Since Jetty 9.4.7, ALPN is also supported using JDK 9 specific APIs without the need of the alpn-boot mechanism. This only works when Jetty is run using JDK 9.
    Since Jetty 9.4.8, ALPN is also supported via the Conscrypt provider, which binds natively to OpenSSL. This is supported for both JDK 8 and JDK 9.
    The advantage of using the Conscrypt provider rather than the default JDK provider is increased performance and increased ease of configuration (since there is no need for the alpn-boot mechanism).
     
    As Java continues to roll out updates and as Jetty continues to bring them into the fold, we will keep you up-to-date on how your implementations might be affected and how best to implement them into your environment.

  • Jetty-9.3 Features!

    Jetty 9.3.0 is almost ready and Release Candidate 1 is available for download and testing!  So this is just a quick blog to introduce you to what is new and encourage you to try it out!

    HTTP2

    The headline feature in Jetty-9.3 is HTTP/2 support. This protocol is now a proposed standard from the IETF and described in RFC7540. The Jetty team has been closely involved with the development of this standard, and while we have some concerns about the result, we believe that there are significant quality of service gains to be had by deploying HTTP/2.   The protocol has features that can greatly reduce the time to render a web page, which is good for clients; plus it has some good economies in using a fewer connections, which is good for servers.

    Jetty has comprehensive support for HTTP/2: Client, Server with negotiated, upgraded and direct connections and the protocol is already supported by the majority of current browsers. Since HTTP2 is substantially based on the SPDY protocol, we have dropped SPDY support from Jetty-9.3.

    Deploying HTTP/2 in the server is just the same as configuring a https connector : java -jar $JETTY_HOME/start.jar --add-to-startd=http2 will get you going (more blogs and doco coming)!

    Webtide is actively seeking users interested in deploying HTTP2 and collaborating on analysis of load, latency, configuration and optimisations.

    ALPN

    To support standard based negotiation of protocols over new connections (eg. to select HTTP2 or HTTPS),  Jetty-9.3 supports the Application Layer Protocol Negotiation mechanism which replaces our previous support for NPN.

    ALPN will automatically be enabled when HTTP2 is enable with start.jar, which downloads a non-eclipse jar containing our own extension to Open JVM and is not covered by the eclipse licenses.

    SNI

    Jetty-9.3 also supports Server Name Indications during TLS/SSL negotiation.  This allows the key store to contain multiple server certificates that have a specific or wild card domain(s) encoded in their distinguished name or by the Subject Alternate Name X.509 extension.     This allows a server with many virtual hosts/contexts to pick the appropriate TLS/SSL certificate for a connection.

    Enabling SNI support is a simple as adding the multiple certificates to your keystore file!

    Java 8

    Jetty-9.3 is built and targeted for Java 8.  This change was prompted by the SNI extension reliance on a Java 8 API and the HTTP2 specification need for TLS ciphers that are only available in Java 8.  It is possible to build Jetty-9.3 for Java 7 and we were considering releasing it as such with a few configuration tricks to enable the few classes that require java 8, however we decided that since java 7 is end-of-life is was not worth the complication to support it directly in the release.   If you really need java 7, then please speak to Webtide about a build of 9.3 for 7.

    Eat What You Kill

    It is impossible to change the protocol as server speaks without dramatic changes on how it is optimized to scale to high loads and low through puts.  The support of HTTP2 requires some fundamental changes to the core scheduling strategies, specifically with regards to the challenge of handling multiplexed requests from a single connection.   Jetty 9.3 contains a new scheduling strategy nicked named Eat What You Kill that makes 9.3 faster out of the box and gives us the opportunity to continue to improve throughput and latency as we tune the algorithm.

    Reactive Asynchronous IO Flows?

    Jetty 9.2 already supports the Servlet Asynchronous IO API and Asynchronous Servlets.  However, in Jetty 9.3 that support has been made even more fundamental and all IO in Jetty is now fundamentally asynchronous from the connector to the servlet streams and robust under arbitrary access from non container managed threads.

    So Jetty-9.3 is a good basis on which to develop with the servlet asynchronous APIs, however as we have some concerns with the complexity of those APIs, we are actively experimenting with better APIs based on Reactive Programming and specifically on the Flow abstraction developed by Doug Lea as a candidate class for Java 9.   We have a working prototype that runs on Jetty-9.3 which we hope to release soon.  Please contact us if you are interested in  participating in this development, as real use-cases are required to test these abstractions!

  • Simple Jetty HelloWorld Webapp

    With the jetty-maven-plugin and Servlet Annotations, it has never been simpler to start developing with Jetty! While we have not quiet achieved the terseness of some convention over configuration environments/frameworks/languages, it is getting close and only 2 files are needed to run a web application!

    Maven pom.xml

    A minimal maven pom.xml is need to declare a dependency on the Servlet API and use the jetty-maven-plugin.   A test project and pom.xml can be created with:

    $ mkdir demo-webapp
    $ cd demo-webapp
    $ gedit pom.xml

    The pom.xml file is still a little verbose and the minimal file needs to be at least:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <packaging>war</packaging>
       <groupId>org.eclipse.jetty.demo</groupId>
       <artifactId>jetty-helloworld-webapp</artifactId>
       <version>1.0</version>
       <dependencies>
         <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>3.1.0</version>
           <scope>provided</scope>
         </dependency>
       </dependencies>
       <build>
         <plugins>
           <plugin>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-maven-plugin</artifactId>
             <version>9.4.5.v20170502</version>
           </plugin>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-war-plugin</artifactId>
             <version>3.0.0</version>
             <configuration>
               <failOnMissingWebXml>false</failOnMissingWebXml>
             </configuration>
           </plugin>
         </plugins>
       </build>
    </project>

    Annotated HelloWorld Servlet

    Maven conventions for Servlet development are satisfied by creating the Servlet code in following source directory:

    $ mkdir -p src/main/java/com/example
    $ gedit src/main/java/com/example/HelloWorldServlet.java

    Annotations allows for a very simple Servlet file that is mostly comprised of imports:

    package com.example;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    @WebServlet(urlPatterns = {"/*"}, loadOnStartup = 1)
    public class HelloWorldServlet extends HttpServlet
    {
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response)
     throws IOException
     {
     response.getOutputStream().print("Hello World");
     }
    }

    Running the Web Application

    All that is left to do is to run the web application:

    $ mvn jetty:run
    

    You can then point your browser at http://localhost:8080/ to see your web application!

    Next Steps

    OK, not the most exciting web application, but it is a start.  From here you could:

    • Clone this demo from github.
    • Add more Servlets or some Filters
    • Add static content in the src/main/webapp directory
    • Create a web deployment descriptor in src/main/webapp/WEB-INF/web.xml
    • Build a war file with mvn install
  • JavaOne 2014 Servlet 3.1 Async I/O Session

    Greg Wilkins gave the following session at JavaOne 2014 about Servlet 3.1 Async I/O.
    It’s a great talk in many ways.
    You get to know from an insider of the Servlet Expert Group about the design of the Servlet 3.1 Async I/O APIs.
    You get to know from the person the created, developed Jetty and implemented Servlet specifications for 19 years what are the gotchas of these new APIs.
    You get to know many great insights on how to write correct asynchronous code, and believe it – it’s not as straightforward as you think !
    You get to know that Jetty 9 supports Servlet 3.1 and you should start using it today 🙂
    Enjoy !