When upgrading from an existing index built with Lucene 8.2.0, Airsonic
fails to start with the following error:
java.lang.IllegalArgumentException: Could not load codec 'Lucene80'. Did you forget to add lucene-backward-codecs.jar?
at org.apache.lucene.index.SegmentInfos.readCodec(SegmentInfos.java:420) ~[lucene-core-8.4.1.jar!/:8.4.1 832bf13dd9187095831caf69783179d41059d013 - ishan - 2020-01-10 13:35:00]
...
at org.apache.lucene.search.SearcherManager.<init>(SearcherManager.java:125) ~[lucene-core-8.4.1.jar!/:8.4.1 832bf13dd9187095831caf69783179d41059d013 - ishan - 2020-01-10 13:35:00]
at org.airsonic.player.service.search.IndexManager.getSearcher(IndexManager.java:309) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.search.IndexManager.getStatistics(IndexManager.java:269) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.MediaScannerService.neverScanned(MediaScannerService.java:121) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.MediaScannerService.schedule(MediaScannerService.java:114) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.MediaScannerService.init(MediaScannerService.java:77) ~[classes!/:10.6.0-SNAPSHOT]
- ID3v24 are now fully supported by jaudiotagger,
there is no need to have special code to handle
them
- Inline a couple of one-line'n'useless methods
- Replace isImageAvailable with getArtwork
- Make some methods static
- Specialise some exceptions
If the library is large enough, Airsonic finishes loading the
application before the first (automatic) scan is completed. The
exception is then shown on the home page until the scan completes.
Fixes#1402
In particular, this should fix an issue described in #884 (and
reproduced since), where Airsonic tries to access the database while
Liquibase has not finished running all the migrations.
2020-01-07 23:00:26.697 ERROR --- o.a.p.service.PodcastService : Failed to initialize PodcastService: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select id, url, title, description, image_url, status, error_message from podcast_channel]; nested exception is java.sql.SQLException: Table not found in statement [select id, url, title, description, image_url, status, error_message from podcast_channel]
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select id, url, title, description, image_url, status, error_message from podcast_channel]; nested exception is java.sql.SQLException: Table not found in statement [select id, url, title, description, image_url, status, error_message from podcast_channel]
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:230) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:654) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:688) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:720) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:730) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:780) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.airsonic.player.dao.AbstractDao.query(AbstractDao.java:93) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.dao.PodcastDao.getAllChannels(PodcastDao.java:73) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.dao.PodcastDao$$FastClassBySpringCGLIB$$9fcd2715.invoke(<generated>) ~[classes!/:10.6.0-SNAPSHOT]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736) ~[spring-aop-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671) ~[spring-aop-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.airsonic.player.dao.PodcastDao$$EnhancerBySpringCGLIB$$b59c1dc5.getAllChannels(<generated>) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.PodcastService.getAllChannels(PodcastService.java:185) ~[classes!/:10.6.0-SNAPSHOT]
at org.airsonic.player.service.PodcastService.init(PodcastService.java:112) ~[classes!/:10.6.0-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:407) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1622) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:211) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1131) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:364) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756) ~[spring-beans-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123) ~[spring-boot-1.5.22.RELEASE.jar!/:1.5.22.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666) ~[spring-boot-1.5.22.RELEASE.jar!/:1.5.22.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353) ~[spring-boot-1.5.22.RELEASE.jar!/:1.5.22.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:300) ~[spring-boot-1.5.22.RELEASE.jar!/:1.5.22.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:135) ~[spring-boot-1.5.22.RELEASE.jar!/:1.5.22.RELEASE]
at org.airsonic.player.Application.main(Application.java:207) ~[classes!/:10.6.0-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[airsonic.war:10.6.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[airsonic.war:10.6.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) ~[airsonic.war:10.6.0-SNAPSHOT]
at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59) ~[airsonic.war:10.6.0-SNAPSHOT]
Caused by: java.sql.SQLException: Table not found in statement [select id, url, title, description, image_url, status, error_message from podcast_channel]
at org.hsqldb.jdbc.Util.throwError(Unknown Source) ~[hsqldb-1.8.0.7.jar!/:private-2006/09/24-10:30:15]
at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source) ~[hsqldb-1.8.0.7.jar!/:private-2006/09/24-10:30:15]
at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source) ~[hsqldb-1.8.0.7.jar!/:private-2006/09/24-10:30:15]
at org.springframework.jdbc.core.JdbcTemplate$SimplePreparedStatementCreator.createPreparedStatement(JdbcTemplate.java:1525) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:632) ~[spring-jdbc-4.3.25.RELEASE.jar!/:4.3.25.RELEASE]
... 61 common frames omitted
In PostgreSQL, Liquibase maps the `blob` type to an `oid` column by
default[1]. That column type is not supported[2] very well when using
the `valueBlobFile` attribute, which expects a `bytea` column instead.
This was confirmed on all PostgreSQL versions starting from 9.6.
The `validCheckSum` attribute does not need to be updated since it was
already for the previous (binary_type, varchar_type) combination in
an unrelated commit (78a99d5860).
Fixes#1213.
[1] https://liquibase.jira.com/browse/CORE-1863
[2] https://github.com/liquibase/liquibase/pull/605
This isn't a perfect solution, but it should help increase confidence
that the transcoder in use is likely to produce an approximately
correct-sized stream.
This switches back to allowing range rather than chunked requests so that
seeking works in the web player, but does so by safer means than previous
solutions, by slightly over-estimating the transcoded size, then sending
dummy bytes to the client to fill any gap. Fixes#1117. Addresses #685.