Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection Service Implementation #140

Merged
merged 5 commits into from
Feb 16, 2016
Merged

Collection Service Implementation #140

merged 5 commits into from
Feb 16, 2016

Conversation

DiegoPino
Copy link
Contributor

Sprint 003 Work and after

What does this Pull Request do?

Implements Collection Service with RDF aggregator.
Implements a pseudo monolithic PCDM Collection microservice implementation using ResourceServiceProvider
This services is built on one POST route, following the same logic as a ResourceService POST Route
Accepts and extra $uuid to be used as base resource for the PCDM collection
Some updates to composer and ResourceServiceProvider (not breaking)

What's new?

The collection Service accepts every RDF language/serialisation EasyRdf accepts via POST
Adds PCDM triples and UUID predicates (with an islandora experimental one) to given rdf body
If RDF body is empty it creates the resources too
Also:

  • Clean up of composer.json to use 0.0.2 chullo package
  • Allows Resource Service Config yaml files to be overridden by implementing app
  • Adds a common route collection to ResourceService unifying some middleware

How should Collection Service be tested?

Similar as the previous ResourceService, only POST Route needed

Basic (Manual testing, be sure to have a working composer environment)

  1. Download/clone/diff/patch
  2. Modify config/settings.dev.yml to match your triplestore and fedora4 URLs, if running without any code change (this settings file depends on the enabled $app['debug'] = true definition in index.php
  3. If testing from a patch update composer.json resource-service version to match your git branch
  4. run $ composer update
  5. run $ php -S localhost:8282 -t src src/index.php this will use the php embed web server to test
  6. Assure you have a fedora4 repo and a triple store running

Assuming you already have some containers in fedora 4 (with nfo:uuid "7ef68f6f-72ab-4708-b0f4-8ec1f07cd580" for example) you can test the working route with a call like this (replace the uuid for one of yours)

  • $ curl -XPOST http://localhost:8282/islandora/collection/7ef68f6f-72ab-4708-b0f4-8ec1f07cd580 -v
    This will create a PCDM collection inside an existing Fedora4 Resource with nfo:uuid "7ef68f6f-72ab-4708-b0f4-8ec1f07cd580" property.
    • This new resource will have two uuid related predicates added with a unique UUID V4 generated by the system (if not already present in rdf body):
      nfo:uuid and isl:hasURN(last one experimental)
    • Will also create an indirect Container with slug members inside the previous PCDM Collection one with triples
      ldp:hasMemberRelation pcdm:hasMember
      ldp:insertedContentRelation ore:proxyFor
  • $ curl -XPOST --data-binary "@body.rdf" -H "Content-Type:text/turtle" "http://localhost:8282/islandora/collection/7ef68f6f-72ab-4708-b0f4-8ec1f07cd580?tx=sometransactionid" -v
    Accepts this query argument optional(the stuff after the ?)
    • tx=transactionid (Will fail if tx given and not a valid transactionid (404))
    • body.rdf should be a file with rdf triples that matches the Content-Type specs: So if using text/turtle it could be something like this
@prefix dc11: <http://purl.org/dc/elements/1.1/> .
<> dc11:title "My Awesome PCDM Collection of dings" .

Note: if you don't have a CLAW vagrant environment working you can use(only for testing)
Note2: look at the response headers… there are a few nice ones!

Additional Notes:

This is a working but "test " Service that needs some cleanups, checks, (like the "use" statements) and can/will be moved in the future.


Thanks a lot!

Diego Pino Navarro
A dog & human friendly developer

Implements Collection Service with RDF aggregator.
Clean up of composer.json to use 0.0.2 chullo package
Allows Resource Service Config yaml files to be overridden by
implementing app
Adds a common route collection to ResourceService unifying some
middleware
In case Content-type is empty default to text/turtle.
Important even when nothing is passed in the body
@daniel-dgi
Copy link
Contributor

Awesome @DiegoPino, thanks for throwing this up.

@DiegoPino
Copy link
Contributor Author

@daniel-dgi thanks. It's kinda monolith, all the code inside the route itself. But on the other side i had to do a lot of header smashing and massaging so for the time being i'm happy with this. Even some static controller invocation in place (noticed that silex is faster than triple indexing!)

@Islandora-CLAW/7-x-2-x-committers i hope you enjoy some extra headers in the response 😄

@daniel-dgi
Copy link
Contributor

@DiegoPino That's not the end of the world. We can refactor that into a service with an interface without too much hassle. Def want to keep those controllers thin so we have DI flexibility.

I can help you out with that if you're agreeable to a pull on pull.

@DiegoPino
Copy link
Contributor Author

@daniel-dgi, i think we can have this as part of the next sprint also. Since object service will be very similar and we could reuse some logic. Could be a good work for new people. I'm also ok with pulls agains pulls. I love pulls.

->value('id',"");

$app->after(function (Request $request, Response $response) use ($app) {
$response->headers->set('X-Powered-By', 'Islandora Collection REST API v'.$app['config']['islandora']['apiVersion'], TRUE); //Nice
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gracias!

@daniel-dgi
Copy link
Contributor

@DiegoPino I'll pull it down and give it a whirl as soon as possible. There's tiny things I could nitpick, like str_replace instead of preg_replace, etc.... But that's kinda pointless. If the code works and is good, I'm happy merging and we can make other tickets to refactor. Haven't checked, but a good phpcbf might be in order too.

@DiegoPino
Copy link
Contributor Author

@daniel-dgi, i'm still confused about silex coding standards. There are recommendations i try to follow(and i my forget a lot) but the examples from symphony are very "ample" in this sense. Also most of the providers i have seen don't use interfaces, so i skipped them also. Oh, yea, str_replace is fine. Just pull against whatever you find weird. thanks!

@daniel-dgi
Copy link
Contributor

@DiegoPino I just use PSR-2 for everything PHP outside of Drupal.

The idea of the interface is just future proofing for later without breaking everything. More of a core tenant of DI than anything else. If we've made it, and we're injecting it, it probably needs an interface. Then we can make services that have alternate implementations (like querying something other than a 3-store) without wrecking everything or having to touch up the controller.

Again, bit much for now. We'll just make seperate tickets. If you want, i'll even assign it to myself just to show folks what I mean.

And I'm not gonna harp on you about str_replace vs. preg_replace. For reals. It's that kind of annoying stuff that discourages contribution. At the end of the day, if a regex turns out to be the performance bottleneck, I'll eat my hat. Or should I say my chullo? :D

@@ -1,8 +1,11 @@
islandora:
apiVersion: 0.0.1
fedoraProtocol: http
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the apiVersion number tied to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ruebot, just an idea i had. Since our api is tied to branch name right now maybe that numbering makes no sense. Any suggestions? thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No suggestions now. Just curious what it was.

Thanks to good @ruebot suggestion.
According to @daniel-dgi suggestion. I hope i did not break anything!
@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Tested works as expected 👍 .

We can merge this and push on to adding additional routes.

  • Create a collection at root (ie. with no UUID).
  • Include RDF or at least a Collection Title.
  • ???

Edit: My mistake, you can skip the UUID to have a collection at the root of the Respository and the request accepts an RDF document which can have a dc:title or more in it.

@ruebot
Copy link
Member

ruebot commented Feb 12, 2016

  • Profit

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Profit? As in a financial gain?

@ruebot
Copy link
Member

ruebot commented Feb 12, 2016

The bullet list with ??? reminded me of the south park underpants gnomes meme 😄

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

I had to look it up, but now I think our project plan should involve the step.

  1. Collect underpants


$urlRoute = $request->getUriForPath('/islandora/resource/');

$subRequestPost = Request::create($urlRoute.$id, 'POST', array(), $request->cookies->all(), array(), $request->server->all(), $pcmd_collection_rdf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why subrequest when you can just use chullo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of reasons, we get all the middleware ,like checking if the base resource is there, header rewriting and we don't need to rewrite psr7 responses. More over, the idea is to not use chullo directly. ResourceService should deal with any new chullo functionality if needed (if we for example need to recode) but not in this higher level services. And since we already using all the other services ResourceService provides, going to chullo when we already have the routes is sub-using our code.

@DiegoPino
Copy link
Contributor Author

@whikloj, the service already creates a collection at root if /$uuid part of the path is not passed
so 1. is resolved. 2. Collection title as param is missing. RDF is working. So passing just the collection title as a simple triple in the body /using any rdf language is also an alternative that can be used right now.

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

As soon as I wrote that I realized that you were passing the Request object which would contain the body. My mistake, going to try that out too.

@DiegoPino
Copy link
Contributor Author

@whikloj, my mistake in the pull description. I will paste an rdf example in the pull description so other people know how to test with @body.rdf

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Tested with putting a Collection at root with a small RDF document. Worked as expected. 👍

@DiegoPino
Copy link
Contributor Author

@whikloj, thanks por testing. Could you strikethrough the missing functionality so other people don't get confused when reading this? Muchas gracias!

@DiegoPino
Copy link
Contributor Author

@whikloj, @daniel-dgi, @ruebot. If you look at the response headers there is a 'link' one too, pointing to a valid islandora claw resource service path.I like the idea we advertise this way how to access the created resource (and to facilitate adding members to the collection once created). I could also append in the future the tx there (i would love the tx would be in some header…is there one suitable for this?)

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Here is my request and response for posterity.

> curl -i -XPOST -H"Content-type: text/turtle" --data-binary "@title.rdf" "http://localhost:8282/islandora/collection"
HTTP/1.1 200 OK
Host: localhost:8282
Connection: close
X-Powered-By: PHP/5.5.32
Server: Apache-Coyote/1.1
ETag: "a18e44b644bbe165f90184eab6d96d6c1d098279"
Cache-Control: private, must-revalidate
Last-Modified: Fri, 12 Feb 2016 15:41:41 GMT
Location: http://localhost:8080/fcrepo/rest/9d/8c/bc/df/9d8cbcdf-7adc-4ea9-b1c7-98c607d0419b/members
Content-Type: text/plain; charset=UTF-8
Content-Length: 90
Date: Fri, 12 Feb 2016 15:41:41 GMT
Link: <http://localhost:8282/islandora/resource/2a69c410-2075-42fa-9c68-67b0984217a3/members>; rel="alternate"
X-Powered-By: Islandora Collection REST API v0.0.1

http://localhost:8080/fcrepo/rest/9d/8c/bc/df/9d8cbcdf-7adc-4ea9-b1c7-98c607d0419b/members

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Actually just thinking, should this return a 201 Created instead of a 200 OK

@DiegoPino
Copy link
Contributor Author

@whikloj, yeah, should be 201, maybe i did something wrong there. I will check (and pull), because i'm returning what i get from the indirect container PUT? mmm… good catch! Update: my fault. fixed!!

@whikloj thanks for catching this
@DiegoPino
Copy link
Contributor Author

For the TX stuff. maybe adding it to Session-Id: header?
https://www.w3.org/TR/WD-session-id

@daniel-dgi
Copy link
Contributor

Keep getting this when trying to composer install, despite having composer install'd the ResourceServiceProvider and providing it's full path in composer.json:

Problem 1
- The requested package islandora/resource-service could not be found in any version, there may be a typo in the package name.

Seen this one before, guys?

@whikloj
Copy link
Member

whikloj commented Feb 12, 2016

Yeah I had that, in composer.json change the require from:
"islandora/resource-service" : "dev-sprint-002",
to
"islandora/resource-service" : "dev-sprint-002-CollectionServ",

or whatever you named @DiegoPino's branch

@daniel-dgi
Copy link
Contributor

Yup, there we go. Knew I was derpin' on that somehwere

@daniel-dgi
Copy link
Contributor

404's when not providing a message body. Is that expected behaviour? Figured we'd just make a collection with no title and slap a uuid on there.

@DiegoPino
Copy link
Contributor Author

@daniel-dgi, are you sure? I get

curl -v -XPOST   "http://localhost:8181/islandora/collection"

* Hostname was NOT found in DNS cachellection"
*   Trying ::1...
* Connected to localhost (::1) port 8181 (#0)
> POST /islandora/collection HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:8181
> Accept: */*
> 
< HTTP/1.1 201 Created
< Host: localhost:8181
< Connection: close
< X-Powered-By: PHP/5.6.16
< Date: Fri, 12 Feb 2016 20:09:01 GMT
< ETag: "896ccfa1c476bcf06967e1fed3e1d55eba176770"
< Cache-Control: private, must-revalidate
< Last-Modified: Fri, 12 Feb 2016 20:09:01 GMT
< Location: http://localhost:8080/rest/d2/c5/03/13/d2c50313-c407-442d-9add-d3ed01bbd9fa/members
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 83
* Server Jetty(9.2.3.v20140905) is not blacklisted
< Server: Jetty(9.2.3.v20140905)
< Link: <http://localhost:8181/islandora/resource/ed05fae2-bcb4-461f-b2d0-251a177da1db/members>; rel="alternate"
< X-Powered-By: Islandora Collection REST API v0.0.1
< 
* Closing connection 0
http://localhost:8080/rest/d2/c5/03/13/d2c50313-c407-442d-9add-d3ed01bbd9fa/members

@daniel-dgi
Copy link
Contributor

Getting this ~ $ curl -v -X POST "http://127.0.0.1:12345/islandora/collection"

  • Hostname was NOT found in DNS cache
  • Trying 127.0.0.1...
  • Connected to 127.0.0.1 (127.0.0.1) port 12345 (#0)

    POST /islandora/collection HTTP/1.1
    User-Agent: curl/7.38.0
    Host: 127.0.0.1:12345
    Accept: /

    < HTTP/1.1 404 Not Found
    < Host: 127.0.0.1:12345
    < Connection: close
    < X-Powered-By: PHP/5.5.27
    < Cache-Control: no-cache
    < Content-Type: text/html; charset=UTF-8
    < X-Powered-By: Islandora Collection REST API v0.0.1
    < Date: Fri, 12 Feb 2016 20:12:46 GMT

Then in the actual message output, i'm getting Silex\Application">Application->abort('404', 'Failed creating PCDM Collection')

@DiegoPino
Copy link
Contributor Author

@daniel-dgi. It's not a bug:
I reproduced your error this way:

  • change your settings.dev.yml to match your settings
  • turn debug off $app['debug'] = true
  • have fedora4 running on 8080
  • run curl -v -X POST "http://127.0.0.1:12345/islandora/collection"
    app runs, tries to connect to fedora on 8080, but fedora responded with a 404 not found. It's not a fedora4 not available, because it's there (if you shut down fedora you get a 503)
    well, i take a look at settings.yml (because i'm using debug off) and realise the production yaml file is pointing to a full install rest endpoint (with fedoraPath: /fcrepo/rest) and i have the jetty version running at fedoraPath: /rest
    So 404 is fine.

Solution check that your settings.dev.yml and/or settings.yml match the fedora endpoint you are using.

@daniel-dgi
Copy link
Contributor

You were close @DiegoPino. I thought i had set those values correctly, but was having weird issues with not being able to resolve localhost. 127.0.0.1 worked just fine.

That's definitely just an env issue on my end.

I've got this working, and it's doing what you say it does.

daniel-dgi added a commit that referenced this pull request Feb 16, 2016
@daniel-dgi daniel-dgi merged commit 46a7669 into Islandora:sprint-002 Feb 16, 2016
@DiegoPino
Copy link
Contributor Author

@daniel-dgi cool! Yeah i had this localhost issues somewhere in the past. Thanks for testing and merging 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants