TAMULib / IRIIIFService

IIIF manifest generator for DSpace RDF and/or Fedora PCDM
MIT License
8 stars 3 forks source link

/fedora/image/ can't create manifest #54

Open andybuki opened 5 years ago

andybuki commented 5 years ago

Hi. I try to create a manifest for images. I already tried it for collection and presentation. It creates a json object properly. One question should it create a json object for the whole collection or only for one object in url?

Now to the error that i get: I created following link: ../fedora/image/dfz/dfz2-B_001156/142/image

I get following error:

2019-03-31 22:13:52.827  INFO 10680 --- [io-9002-exec-10] e.t.i.service.AbstractManifestService    : Generating new manifest.
java.io.IOException: Incorrect response status: 404
    at edu.tamu.iiif.service.HttpService.request(HttpService.java:119)
    at edu.tamu.iiif.service.HttpService.get(HttpService.java:100)
    at edu.tamu.iiif.service.HttpService.get(HttpService.java:74)
    at edu.tamu.iiif.service.AbstractManifestService.fetchImageInfo(AbstractManifestService.java:250)
    at edu.tamu.iiif.service.fedora.pcdm.FedoraPcdmImageManifestService.generateManifest(FedoraPcdmImageManifestService.java:22)
    at edu.tamu.iiif.service.AbstractManifestService.getManifest(AbstractManifestService.java:119)
    at edu.tamu.iiif.controller.AbstractManifestController.sendManifest(AbstractManifestController.java:27)
    at edu.tamu.iiif.controller.fedora.pcdm.FedoraPcdmImageManifestController.manifest(FedoraPcdmImageManifestController.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
2019-03-31 22:13:52.874  WARN 10680 --- [io-9002-exec-10] edu.tamu.iiif.service.HttpService        : Error performing GET request: http://localhost:8182/iiif/2/8d52d264-a367-4710-af13-ed6acfca7150
2019-03-31 22:13:52.876  WARN 10680 --- [io-9002-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: edu.tamu.iiif.exception.NotFoundException: Image information not found!
jcreel commented 5 years ago

Hi andybuki, It’s great that you can generate the collection and presentation manifests. To find out what’s wrong with image manifest generation, it would be useful to know more about the structure of your Fedora repository. It should be noted that the tool works with content that is structured according to PCDM: https://pcdm.org. Can you also confirm that your external IIIF Image Server is working properly? The service has only been tested with Cantaloupe. It looks like the 404 is happening when it tries to grab the info.json. Thanks for reporting this issue.

andybuki commented 5 years ago

Hi jcreel, thanks for your answer. Hier is an examle of my Fedora. I built it using JSON-LD. I have following structure: collection->book->page->image Book examle:

book

Image example:

image

I use curl command to add to Fedora. As image server i use Cantaloupe. Before testing i start Cantaloupe and Redis. In application.yaml

fedora:
    url: http://b-dev998:8081/fcrepo/rest
    identifier:
      fedora-pcdm: fedora

In Browser i tried to call image:

http://localhost:9002/fedora/image/Meiji_Japan/23906book/49/image/19/c7/c6/50/19c7c650-cc3f-46f1-a85e-4cac870cf77e/fcr:metadata
http://localhost:9002/fedora/image/Meiji_Japan/23906book/49/image/19/c7/c6/50/19c7c650-cc3f-46f1-a85e-4cac870cf77e/
http://localhost:9002/fedora/image/Meiji_Japan/23906book/49/image/

But i always got the same error, Image information not found!

andybuki commented 5 years ago

Hi. again.

I just take the following example and created a simple fedora collection: https://ublinnovatie.files.wordpress.com/2016/09/hands-on-with-fedora-4.pdf collection->book->page->image

And try to call this collection via IRIIIFService.

It creates collection, presentation json file, but for image i get the same error.

ghost commented 5 years ago

It seems as there is no delegate resolver setup for Cantaloupe to use the IRIIIFService file resolver.

Here is a template of the delegate function we use:

  ##
  # @param options [Hash] Empty hash.
  # @return [String,Hash<String,String>,nil] String URI; Hash with `uri` key,
  #         and optionally `username` and `secret` keys; or nil if not found.
  #
  def httpsource_resource_info(options = {})
    id = context['identifier']
    puts id
    if ( id =~ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ )
      uri = '<%= @iiif_service_url %>resources/' + id + '/redirect'
    elsif
      irid = Base64.decode64(id)
      puts irid
      if irid.include? ":"
        parts = irid.split(':')
        ir = parts[0]
        path = parts[1]
        if ir == 'fedora'
          uri = '<%= @fedora_url %>' + path
        elsif ir == 'dspace'
          uri = '<%= @dspace_url %>' + path
        else
          uri = irid
        end
      else
        uri = id
      end
    end
    puts uri
    return uri
  end

Our PoC legacy approach was to base64 encode and decode URL paths. Since, we have added resolver API using Redis on the IRIIIFService itself. When Cantaloupe receives the identifier from the manifest, it has to resolve it and this delegate asks the IRIIIFService for the URI of the image to resolve.

We hope to soon update documentation to be more comprehensive.

I hope this helps.

andybuki commented 5 years ago

Hi William, thanks for answer. I really fogot to add change delegate.rb and change this parameter in cantaloupe.properties to true.

But i still have the same error with images. Now i test it everything localy. Cantaloupe has following logs:

09:43:24.158 [qtp1053782781-19] INFO  e.i.l.c.s.FilesystemSource - Resolved c182e30a-d613-40ca-baab-55ee2691aa1e to \home\myself\images\c182e30a-d613-40ca-baab-55ee2691aa1e
09:43:24.160 [qtp1053782781-19] DEBUG e.i.l.c.r.AbstractResource - X-Forwarded headers: Proto: http; Host: null; Port: null; Path:
09:43:24.163 [qtp1053782781-19] DEBUG e.i.l.c.r.AbstractResource - Base URI assembled: http://localhost:8182
09:43:30.507 [qtp1053782781-14] DEBUG e.i.l.c.r.AbstractResource - Identifier requested: ef4c01ee-a10a-4355-82e1-90d428f2337e -> decoded: ef4c01ee-a10a-4355-82e1-90d428f2337e -> slashes substituted: ef4c01ee-a10a-4355-82e1-90d428f2337e
09:43:30.508 [qtp1053782781-14] INFO  e.i.l.c.r.AbstractResource - doInit(): handling GET http://localhost:8182/iiif/2/ef4c01ee-a10a-4355-82e1-90d428f2337e [Connection: keep-alive; User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_201); Host: localhost:8182; Accept-Encoding: gzip,deflate]
09:43:30.510 [qtp1053782781-14] DEBUG e.i.l.c.r.AbstractResource - X-Forwarded headers: Proto: http; Host: null; Port: null; Path:
09:43:30.510 [qtp1053782781-14] DEBUG e.i.l.c.r.AbstractResource - Base URI assembled: http://localhost:8182
09:43:30.514 [qtp1053782781-17] DEBUG e.i.l.c.r.AbstractResource - Identifier requested: ef4c01ee-a10a-4355-82e1-90d428f2337e -> decoded: ef4c01ee-a10a-4355-82e1-90d428f2337e -> slashes substituted: ef4c01ee-a10a-4355-82e1-90d428f2337e
09:43:30.515 [qtp1053782781-17] INFO  e.i.l.c.r.AbstractResource - doInit(): handling GET http://localhost:8182/iiif/2/ef4c01ee-a10a-4355-82e1-90d428f2337e/info.json [Connection: keep-alive; User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_201); Host: localhost:8182; Accept-Encoding: gzip,deflate]
09:43:30.517 [qtp1053782781-17] DEBUG e.i.l.c.r.AbstractResource - Identifier requested: ef4c01ee-a10a-4355-82e1-90d428f2337e -> decoded: ef4c01ee-a10a-4355-82e1-90d428f2337e -> slashes substituted: ef4c01ee-a10a-4355-82e1-90d428f2337e
09:43:30.523 [qtp1053782781-17] DEBUG e.i.l.c.s.DelegateProxy - invokeUncached(): invoking context= with args: ({identifier=ef4c01ee-a10a-4355-82e1-90d428f2337e, request_headers={Connection=keep-alive, User-Agent=Apache-HttpClient/4.5.3 (Java/1.8.0_201), Host=localhost:8182, Accept-Encoding=gzip,deflate}, client_ip=127.0.0.1, request_uri=http://localhost:8182/iiif/2/ef4c01ee-a10a-4355-82e1-90d428f2337e/info.json, cookies={}})
NoMethodError: undefined method `context=' for #<CustomDelegate:0x11adb12e>
09:43:30.531 [qtp1053782781-17] ERROR e.i.l.c.s.DelegateProxy - java.lang.NoSuchMethodException: (NoMethodError) undefined method `context=' for #<CustomDelegate:0x11adb12e>
09:43:30.532 [qtp1053782781-17] INFO  e.i.l.c.s.FilesystemSource - Resolved ef4c01ee-a10a-4355-82e1-90d428f2337e to \home\myself\images\ef4c01ee-a10a-4355-82e1-90d428f2337e
09:43:30.533 [qtp1053782781-17] DEBUG e.i.l.c.r.AbstractResource - X-Forwarded headers: Proto: http; Host: null; Port: null; Path:
09:43:30.534 [qtp1053782781-17] DEBUG e.i.l.c.r.AbstractResource - Base URI assembled: http://localhost:8182

application.yaml looks following:

server:
  contextPath:
  port: 9002

logging:
  file: ir-iiif-service.log
  level:
    edu.tamu.iiif: INFO
    org.springframework: INFO
  path: /var/logs/iiif

spring:
  redis:
    host: localhost
    port: 6379
  profiles:
    active: production
    include: fedora

iiif:
  admins:
    -
      username: admin
      password: abc123
  service:
    url: http://localhost:${server.port}${server.contextPath}
    connection:
      timeout: 1200000
      timeToLive: 1200000
      request.timeout: 600000
    socket.timeout: 1800000
  image.server.url: http://localhost:8182/iiif/2
  logo.url: https://brandguide.tamu.edu/assets/downloads/logos/TAM-Logo.png
  dspace:
    url: http://localhost:8080
    webapp: xmlui
    identifier:
      dspace-rdf: dspace
  fedora:
    url: http://localhost:9001/fcrepo/rest
    identifier:
      fedora-pcdm: fedora

If you have any ideas, where i made a mistake or fogot something, it will be very nice.

Andrey

andybuki commented 5 years ago

Presentation API:


  "@context" : "http://iiif.io/api/presentation/2/context.json",
  "@id" : "http://localhost:9002/fedora/presentation/david-wilcox/book-collection/book1",
  "@type" : "sc:Manifest",
  "description" : "No description available!",
  "label" : "The Story of My Life",
  "logo" : "https://brandguide.tamu.edu/assets/downloads/logos/TAM-Logo.png",
  "metadata" : [ {
    "label" : "title",
    "value" : "The Story of My Life"
  }, {
    "label" : "creator",
    "value" : "Test"
  } ],
  "sequences" : [ {
    "@id" : "http://localhost:9002/fedora/sequence/david-wilcox/book-collection/book1",
    "@type" : "sc:Sequence",
    "canvases" : [ ],
    "label" : "The Story of My Life"
  } ]
}
ghost commented 5 years ago

Cantaloupe is not resolving the images yet. Therefore, cannot get image manifest to know how populate the sequence with canvases.

It appears Cantaloupe needs a bit more configuration. In cantaloupe.properties make sure you are using a HttpSource, source.static = HttpSource, and that the HttpSource is using ScriptLookupStrategy, HttpSource.lookup_strategy = ScriptLookupStrategy.

You may also want to configure and setup various image processors. We really on Kakadu, as it is the most performant for jp2000.

andybuki commented 5 years ago

Hi William, may be you have an example rdf file or json-ld for Fedora, that I can improve my images in Fedora, that they are able to move into image server.

ghost commented 5 years ago

Here are some very basic Fedora rdf responses used in the tests.

https://github.com/TAMULib/IRIIIFService/tree/master/src/test/resources/mock/fedora/rdf

The resource images in Fedora will need their mimetype specified. Can use the ebucore schema.

https://github.com/TAMULib/IRIIIFService/blob/master/src/test/resources/mock/fedora/rdf/item_container_files_entry.rdf#L47

ghost commented 5 years ago

@andybuki have you had any progress with this? Apologize for the incomplete documentation.

andybuki commented 5 years ago

Hi William, honestly i didn't tried it again. Next week i'll have more time to test it again. I want to use your service, because we have huge Fedora collections, that i want to connect with IIIF service.

ghost commented 5 years ago

That is what this is designed for. Generating manifests from large collections takes time. Caching is ideal for this. There has been some fixes recently. Specifically, there was an issue where a fedora collection was not following hasMembers and only a proxyOrder. It now traverses hasMembers if a proxyOrder is not specified. There are also some more patch PRs.