Artificial truth

The more you see, the less you believe.

[archives] [latest] | [homepage] | [atom/rss/twitter]

Making Ultrasonic work with Airsonic on Java 11
Sun 01 September 2019 — download

If like me you're using Ultrasonic to interact with your airsonic instance, you might have wondered why it stopped working when you updated to a new java version.

Airsonic is a fork of the now-defunct libresonic, itself a fork of the now-non-free subsonic, hence why it's exposing the API of the later.

Unfortunately, subsonic being a freemium software, to use the API, one has to have a valid license. This is why mobile applications are first calling the /rest/getLicense.view endpoint, before being able to use it.

On airsonic, this is a dummy endpoint, implemented in SubsonicRESTController.java:

    /**                                                                          
     * CAUTION : this method is required by mobile applications and must not be removed.
     */                                                                          
    @RequestMapping(value = "/getLicense")                                                                                                                                
    public void getLicense(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request = wrapRequest(request);                                          
        License license = new License();                                         


        license.setEmail("airsonic@github.com");                                 
        license.setValid(true);                                                  
        Date neverExpireDate = new Date(Long.MAX_VALUE);                         
        license.setLicenseExpires(jaxbWriter.convertDate(neverExpireDate));      
        license.setTrialExpires(jaxbWriter.convertDate(neverExpireDate));        

        Response res = createResponse();                                         
        res.setLicense(license);                                                 
        jaxbWriter.writeResponse(request, response, res);                        
    }    

The issue is that something changed between Java8 and Java11 when it comes to new Date(Long.MAX_VALUE), resulting in a 08-26 09:50:01.763 14652 14652 W BackgroundTask: Got exception: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of typejava.util.Calendarfrom String "292278994-08-17T07:12:55.807Z": not a valid representation (error: Failed to parse Date value '292278994-08-17T07:12:55.807Z': Cannot parse date "292278994-08-17T07:12:55.807Z": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd")) exception on the application's side.

While the issue is being worked on upstream, if you're too lazy to recompile the -git version, a simple workaround is to add the following to your nginx configuration:

    location /rest/getLicense.view {
                alias /var/airsonic/license.json;
        }

with /var/airsonic/license.json containing something like this:

{
    "subsonic-response" : {
        "status" : "ok",
            "version" : "1.15.0",
            "license" : {
                "valid" : true,
                "email" : "airsonic@github.com",
                "licenseExpires" : "4096-01-01T07:12:55.807Z",
                "trialExpires" : "4096-01-01T07:12:55.807Z"
            }
    }

And voilà, Ultrasonic is working again.