Flash is dying, and I’m one of the few people who’ll miss it. While Flash was and is a terrible security risk, it solved one problem almost completely by accident: sending video to many people with a low delay. Working with online auctions, delay means a lot to me. If the viewers are actually bidding in a real-time auction, a delay of a few seconds is a problem. If they’re bidding against people who are actually at the auction, it’s impossible. By the time the remote buyer hears a bid from the auction hall, buyers who are physically there can bid again several times.
The RTMP protocol used by Flash requires a direct TCP connection from the browser to the video server: this allows an end to end delay of less than a second, while making it impossible to set up a shared cache infrastructure or CDN. Modern streaming protocols such as HLS and DASH are CDN friendly, by breaking the video into segments of around 1 to 10 seconds. This segmentation forces an end-to-end delay of at least one segment duration.
It’s actually a little worse than that, because each segment should be an independent video file, and not depend on any previous file. So as the file duration gets shorter, the efficiency gets less. At the limit, if each segment was a single frame of video, it would be equivalent to sending a sequence of JPEG files.
And iOS? WebRTC is marked as “in development” for WebKit, but we don’t know when, or whether this will be available on iOS Safari. Until then Apple doesn’t support any low-latency protocol in their web browser, so there’s no alternative to an app for that.
We recently moved an application to a new server, with an updated installation of Java 8. It didn’t take long to discover that Amazon S3 accesses were failing with an authentication error, and it didn’t take much longer to discover that this problem was already fixed in the version of the AWS Java SDK we were using.
com.amazonaws.services.s3.model.AmazonS3Exception: AWS authentication requires a valid Date or x-amz-date header
The real problem was that we had many dependencies on different versions of Joda Time, and AWS had lost the battle - we were actually running Joda Time 2.0.
It was time to stop this happening again, with the Maven Enforcer Plugin. It’s possible to fail the build if we ever reference two versions of the same dependency:
I’m integrating Quartz scheduling into an application, and was looking for an annotation based approach to configuration. I quickly found the SivaLabs implementation, which works for Quartz 1.8. I’ve made a few changes to use this with Spring 4.1.4 and Quartz 2.2.3.
The custom annotation remains the same:
The major change is that I have replaced the ApplicationListener class with a bean that performs a single scan of a selected package. I chose this approach because my configuration does not change once loaded, and I wanted to throw a fatal exception on any error in Quartz configuration. I’ve refactored to add each job to the scheduler as it is discovered, rather than building an intermediate list.
The CronTriggerBean and JobDetailBean from Spring 3 are gone in Spring 4. The new code builds the job using the Quartz 2 fluent builders, rather than Spring’s factory beans:
The job factory is unchanged from the original article, and the XML configuration looks like this:
At this point jobs are automatically configured as long they:
implement the Job interface
have the QuartzJob annotation
are in a package scanned by Spring, and by the QuartzJobScanner
We have a monolith. It’s not the biggest monolith, but it does contain a lot of Java libraries, managed with Maven. This week an upgrade to one package caused a distant side effect.
Our monolith is a web application, and uses an embedded Jetty server. It also uses Jasper reports, compiling jrxml files on demand. This week, our builds stopped compiling reports, with an exception that Jasper could not find javac. The first thought was that somebody had changed the server install from a JDK to a JRE, leaving the compiler unavailable. But after installing the latest JDK, and checking the system path, the error changed:
net.sf.jasperreports.engine.JRException: Errors were encountered when compiling report expressions class file:
C:\Users\adrian\Workspaces\Customer\App\App-Web\j491845presale_seller_1464295746680_612367.java:227: error: cannot find symbol
value = DATEFORMAT(((java.sql.Timestamp)field_sale_start.getValue()), "dd/MM/YYYY"); //$JR_EXPR_ID=2$
symbol: method DATEFORMAT(Timestamp,String)
location: class j491845presale_seller_1464295746680_612367
As jasperreports-functions-5.6.1.jar was in the classpath, there was clearly another problem. Why was Jasper searching for javac at all, when Eclipse JDT was available?
The next step was to go through our commits to find the point where things went wrong. It didn’t take long to discover the breakage was caused by an upgrade from Jetty 9.0 (2013) to Jetty 9.3 (2016). But how had this broken Jasper?
Stepping through Jasper initialisation reveals that Jasper attempts to load org.eclipse.jdt.internal.compiler.env.AccessRestriction in order to discover which version of JDT is present. This attempt fails, even though the class is present on the classpath.
This turned my debugging attention to the classloader. Jetty includes a WebAppClassloader, and setting a breakpoint in its loadClass method revealed that the JDT class was identified as a server class. Knowing this cause, it didn’t take long to find the commit that broke Jasper on Github.
As our application uses Jetty as an embedded web server, I disabled the WebAppClassloader like this, and Jasper reports worked again: