geotrellis / geotrellis-transit

API and libraries for generating travelsheds from OSM & GTFS data
Other
40 stars 20 forks source link

Fix issue with assembly's ClassNotFound exception #83

Closed lossyrob closed 7 years ago

lossyrob commented 7 years ago

The issue was with GeoTools, and how it stores it's projection information. There are multiple dependencies from the GeoTools that have the same files in their META_INF pertaining to the projection info, namely:

META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory
META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory
META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory

These files were being merged in the assembly process using the merge strategy "first", which is what the build.sbt declares as the default. This PR moves it to use the "last" strategy. This makes the proper files remain in the assembly, proper files meaning the ones that make it not crash. If these seems hand wavy, it's because it is. I tried it and it happens that the merge strategy bakes in the right files.

One thing to note is that the "ClassNotFound" exception wasn't a good description of the fail. I believe it was due to the way Jetty loads in service classes using reflection. When I moved a reference to Reproject to the first lines in the main method, I got a different error:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at geotrellis.transit.services.Reproject$.initCache(ServiceUtil.scala:39)
    at geotrellis.transit.services.Reproject$.<init>(ServiceUtil.scala:43)
    at geotrellis.transit.services.Reproject$.<clinit>(ServiceUtil.scala)
    at geotrellis.transit.Main$.main(Main.scala:35)
    at geotrellis.transit.Main.main(Main.scala)
Caused by: org.opengis.referencing.NoSuchAuthorityCodeException: No code "EPSG:3857" from authority "EPSG" found for object of type "EngineeringCRS".
    at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.noSuchAuthorityException(CartesianAuthorityFactory.java:136)
    at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.createEngineeringCRS(CartesianAuthorityFactory.java:130)
    at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.createCoordinateReferenceSystem(CartesianAuthorityFactory.java:121)
    at org.geotools.referencing.factory.AuthorityFactoryAdapter.createCoordinateReferenceSystem(AuthorityFactoryAdapter.java:801)
    at org.geotools.referencing.factory.ThreadedAuthorityFactory.createCoordinateReferenceSystem(ThreadedAuthorityFactory.java:731)
    at org.geotools.referencing.DefaultAuthorityFactory.createCoordinateReferenceSystem(DefaultAuthorityFactory.java:179)
    at org.geotools.referencing.CRS.decode(CRS.java:489)
    at org.geotools.referencing.CRS.decode(CRS.java:417)
    at geotrellis.transit.services.Projections$.<init>(ServiceUtil.scala:23)
    at geotrellis.transit.services.Projections$.<clinit>(ServiceUtil.scala)
    ... 5 more

Also in the PR:

tnation14 commented 7 years ago

👍 This works great; production JAR builds and that exception isn't popping up. Thanks!