Skip to content

Using CLAW PHP Microservices

Jared Whiklo edited this page May 16, 2016 · 3 revisions

All of these examples are using the PHP microservices. This is not using the Camel services.

Table of Contents

  1. Setup the Virtual Machine
  2. Microservice configuration
  3. Create a resource in Fedora
  4. "PUT"ing an object in Fedora
  5. "POST"ing an object to Fedora
  6. Delete a resource from Fedora
  7. Create a PCDM Collection
  8. Adding a member to a pcdm:Collection
  9. Deleting a member from a pcdm:Collection

Setup the Virtual Machine

This assumes you have a working vagrant environment.

  1. Clone this repository (https://github.com/Islandora-CLAW/CLAW.git) to a new location that does not overlap with your old Islandora code.

git clone https://github.com/Islandora-CLAW/CLAW.git CLAW 2. Checkout the sprint-002 branch.

```

cd CLAW git checkout -b sprint-002 origin/sprint-002

 2. Go to the **install** sub-directory and start the vagrant virtual machine.

    ```
cd install
vagrant up
  1. Once it has completed successfully you should see something like this

    ==> default: paragonie/random_compat suggests installing ext-libsodium (Provides a modern crypto API that can be used to generate random bytes.)
    ==> default: ramsey/uuid suggests installing ramsey/uuid-console (A console application for generating UUIDs with ramsey/uuid)
    ==> default: ramsey/uuid suggests installing ircmaxell/random-lib (Provides RandomLib for use with the RandomLibAdapter)
    ==> default: ramsey/uuid suggests installing ext-uuid (Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator)
    ==> default: ramsey/uuid suggests installing moontoast/math (Provides support for converting UUID to 128-bit integer (in string form).)
    ==> default: ramsey/uuid suggests installing ramsey/uuid-doctrine (Allows the use of Ramsey\Uuid\Uuid as Doctrine field type.)
    ==> default: ramsey/uuid suggests installing ext-libsodium (Provides the PECL libsodium extension for use with the SodiumRandomGenerator)
    ==> default: Writing lock file
    ==> default: Generating autoload files
    
 4. You now have a virtual machine with:
   * Drupal at http://localhost:8000
   * [Fedora 4](https://wiki.duraspace.org/display/FF/Fedora+Repository+Home) at http://localhost:8080/fcrepo/rest
   * [Blazegraph](https://wiki.blazegraph.com/wiki/index.php/Main_Page) at http://localhost:8080/bigdata
   * Apache Karaf at http://localhost:8181
   * CLAW PHP microservices at http://localhost:8282/

 5. With your VM up and running you can browse to <a href="http://localhost:8080/fcrepo/rest" target="_blank">your Fedora instance</a>.
You should see something like this. 
[[https://github.com/whikloj/microservice_example/blob/master/images/blank_fcrepo.jpg|alt=Fedora4]]

 5. Have fun 

[return to top](#table-of-contents)

---
# Microservice configuration

Each microservice has a configuration file (or multiple) located in a **config** directory. These files are written in [YAML](http://yaml.org/) and are pretty clear. 

However, if you encounter errors like:
`Chullo says "Triple Store Not available"`

Then your configuration file is probably incorrect.

For most we are currently using the `settings.dev.yml` version as the microservices have ``$app['debug'] = TRUE;`.

If you set `$app['debug'] = FALSE;` or remove it (because FALSE is the default). Then it will read the `settings.yml` file instead.

The `settings.dev.yml` file for the services looks like this.
```yaml
# Islandora Dev Settings to be used with $app['debug'] == TRUE
islandora:
  fedoraProtocol: http
  fedoraHost: "localhost:8080"
  fedoraPath: /fcrepo/rest
  tripleProtocol: http
  tripleHost: "localhost:8080"
  triplePath: /bigdata/sparql
  resourceIdRegex: "(?:[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?"
# This domain is used as namespace (hashed) when generating UUID V5 identifiers
  defaultNamespaceDomainUuuidV5: "www.islandora.ca"

So if your Fedora or your triplestore was at a different location, you would need to update it here.

return to top


Create a resource in Fedora

For this we'll use cURL, if you don't have access from your machine you can log into the virtual machine by typing vagrant ssh from the /install directory (same place you typed vagrant up).

This makes use of the ResourceService and is meant to send the data you give it to Fedora with altering it.

"PUT"ing an object in Fedora

  1. Create a file in your current directory called object.ttl.

    This will be a text file of RDF and the format we are going to use is Turtle (here is a helpful tutorial on the syntax).

    But you could also use N-Triples, N3, RDF XML or JSON-LD.

  2. Add the following to your object.ttl file:

@prefix pcdm: http://pcdm.org/models# . @prefix nfo: http://www.semanticdesktop.org/ontologies/2007/03/22/nfo/v1.2/ . @prefix dc: http://purl.org/dc/elements/1.1/ .

<> a pcdm:Object ; dc:title "Object Number 1" ; nfo:uuid "4a51d7bc-83ed-4468-803a-17c411520bc0" .


    The UUID is one I generated [here](https://www.uuidgenerator.net/), each object should have a unique UUID. So if you want to create multiple objects with this file, make sure to change the UUID before you post it again.

3. We are going to use the [**PUT**](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) method, which means we can tell Fedora where to put it and what to call it. We will put a resource right at the root of the repository and call it **object1**.

    `curl -i -XPUT -H"Content-type: text/turtle" --data-binary "@object.ttl" http://localhost:8282/islandora/resource//object1`

    **Important** to use the **PUT** HTTP method to create a resource at the **root** level, you need to have **2** backslashes between `resource` and the name of the object.

If all goes well you should see something like:

HTTP/1.1 201 Created Date: Thu, 24 Mar 2016 02:17:49 GMT Server: Apache/2.4.7 (Ubuntu) X-Powered-By: PHP/5.5.9-1ubuntu4.14 ETag: "18112aa1d85a3448236ec82164ab15bc2d9e2ec8" Cache-Control: private, must-revalidate Last-Modified: Thu, 24 Mar 2016 02:17:49 GMT Location: http://localhost:8080/fcrepo/rest/object1 Content-Length: 41 Connection: close Content-Type: text/plain; charset=UTF-8

http://localhost:8080/fcrepo/rest/object1


This is the response direct from Fedora, so you see the Fedora URL in the `Location:` header and the body.


If you browse to [http://localhost:8080/fcrepo/rest/object1](http://localhost:8080/fcrepo/rest/object1) you should see your object in the Fedora interface.
[[https://github.com/whikloj/microservice_example/blob/master/images/fcrepo_object1.jpg|alt="Object 1 in Fedora"]]

Congrats!

[return to top](#table-of-contents)

---
## "POST"ing an object to Fedora

You can also perform the above steps but use a [**POST**](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) instead of a **PUT**, the difference is that you provide no name and Fedora creates one for you.

Let's create another object as a child of **object1**.

1. Open your **object.ttl** file and edit it to the following:

    ```
@prefix pcdm: <http://pcdm.org/models#> .
@prefix nfo: <http://www.semanticdesktop.org/ontologies/2007/03/22/nfo/v1.2/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<> a pcdm:Object ;
  dc:title "Object Number 2" ;
  nfo:uuid "5fa71ed6-f5f3-4831-8662-b1b132815a52" .
**Hint**: I've modified the *dc:title* and the *nfo:uuid* to be different from **object1**.

Now if we look back at [the routes](https://github.com/whikloj/islandora/blob/sprint-002-thinCollection/services/ResourceService/src/Provider/ResourceServiceProvider.php#L142-L143) you'll see that the POST route only accepts one parameter. This is the parent Uuid or nothing to place it at the root level.

To place our resource as a child of **object1** we need to get the UUID of **object1**. You can check Fedora and copy the UUID, it appears in the properties like this.

[[https://github.com/whikloj/microservice_example/blob/master/images/fcrepo_uuid.jpg|alt="Fedora 4 with nfo:uuid"]]
  1. Let's use the UUID in our command.

    curl -i -XPOST -H"Content-type: text/turtle" --data-binary "@object.ttl" http://localhost:8282/islandora/resource/4a51d7bc-83ed-4468-803a-17c411520bc0

If your above command works you'll see something like:

HTTP/1.1 201 Created
Date: Thu, 24 Mar 2016 02:32:04 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
ETag: "6605471b8cd6f18a1d9b1170511f26f8bc156785"
Cache-Control: private, must-revalidate
Last-Modified: Thu, 24 Mar 2016 02:32:05 GMT
Location: http://localhost:8080/fcrepo/rest/object1/4d/7c/07/83/4d7c0783-7efd-46de-adf6-ac0bda9784a7
Content-Length: 90
Connection: close
Content-Type: text/plain; charset=UTF-8

http://localhost:8080/fcrepo/rest/object1/4d/7c/07/83/4d7c0783-7efd-46de-adf6-ac0bda9784a7

Note: Your Location will NOT be the same as above, but should otherwise the results should be the same.

If you browse to the URL in the Location header you should see your new Object Number 2.

You'll also notice that it has a property fedora:hasParent http://localhost:8080/fcrepo/rest/object1.

If you click on that link and goto Object Number 1 you'll that it has a complementary property ldp: contains http://localhost:8080/fcrepo/rest/object1/4d/7c/07/83/4d7c0783-7efd-46de-adf6-ac0bda9784a7

Again remember that your URL for Object Number 2 will be different from above.

Awesome.

return to top


Delete a resource from Fedora

Deleting a resource is much the same. Let's delete Object Number 2.

To delete we use the DELETE HTTP method, and the UUID for the resource.

Object Number 2 has a nfo:UUID of 5fa71ed6-f5f3-4831-8662-b1b132815a52.

Aside: The theory in linked data is that rarely would you want to reuse a URL, once that URL has been associated with a object/resource/whatever. You might delete it, but rarely will you use it again. Tombstones are left behind by Fedora 4 (API) when you delete a resource. They are located at http://localhost:8080/fcrepo/rest/path/to/resource/fcr:tombstone.

You can delete a tombstone and the microservices deal with that by accepting a ?force=true querystring on the URL.

So....

  1. To delete only Object Number 2 and leave the tombstone, you do:

    curl -i -XDELETE http://localhost:8282/islandora/resource/5fa71ed6-f5f3-4831-8662-b1b132815a52

  2. To delete Object Number 2 and remove it's tombstone, you do

    curl -i -XDELETE http://localhost:8282/islandora/resource/5fa71ed6-f5f3-4831-8662-b1b132815a52?force=true

Whichever you choose to do you should see:

HTTP/1.1 204 No Content
Date: Thu, 24 Mar 2016 02:46:10 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Connection: close
Cache-Control: no-cache
Content-Length: 0
Content-Type: text/html

The object is gone, you can check with your browser at the old URL. You can also check object1 and notice that it no longer ldp:contains anything.

return to top


Create a PCDM Collection

Everything before this has been creating straight Fedora 4 objects. Now we will use a more complex microservice to create a PCDM Collection object.

The CollectionService has 3 routes

  • The first creates a Collection by POSTing to /islandora/collection.
  • The second adds an object as a member of the collection by POSTing to /islandora/collection/<collection uuid>/member/<object uuid>
  • The third removes an object from a collection by DELETE'ing to /islandora/collection/<collection uuid>/member/<object uuid>

This microservice is slightly different from the ResourceService in that we know that a Collection needs a UUID to be used by CLAW. So if you don't provide one, then one will be set

What this means is even if we don't provide a UUID, one will be assigned automatically.

  1. So let's create a pcdm:Collection at the root level

    curl -i -XPOST http://localhost:8282/islandora/collection

    There is currently no PUT route, so you can't yet specify the path of the resource.

The above will result is something like

HTTP/1.1 201 Created
Date: Thu, 24 Mar 2016 03:09:36 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
ETag: "7253f1619e0954a11c5f1138ea55ba9cbe6f3cd2"
Cache-Control: private, must-revalidate
Last-Modified: Thu, 24 Mar 2016 03:09:37 GMT
Location: http://localhost:8282/islandora/resource/f07c0d38-8290-4c2d-877c-233dfce374ea
Content-Length: 77
Connection: close
Link: <http://localhost:8282/islandora/resource/f07c0d38-8290-4c2d-877c-233dfce374ea/members>; rel="hub"
Content-Type: text/plain; charset=UTF-8

http://localhost:8282/islandora/resource/f07c0d38-8290-4c2d-877c-233dfce374ea

You'll notice that the Location and Link headers as well as the body of the response all refer to our microservices. In fact if you go in your browser to the URL in your Location header. You will see the RDF for that object returned by the microservices.

Or we can use the microservices with curl...

curl -i http://localhost:8282/islandora/resource/f07c0d38-8290-4c2d-877c-233dfce374ea

Which will display the RDF for your Collection object.

You should actually go to your Fedora repository and look at the Collection, because we actually created 2 objects.

We created the pcdm:Collection object, and then we created a child called members that is an Indirect Container

Here you can see the UUID, the rdf:type of pcdm:Collection and a ldp:contains with members.

Click on the child link and let's look at it.

The 3 important properties on this indirect container are

Those 3 properties define how we will add a property somewhere else in the repository whenever an object is added to this indirect container.

When we add an object to this indirect container, it will check to see if that object has a property matching the ldp:insertedContentRelation. It will then add a new property to the resource defined by ldp:membershipResource with a relationship of ldp:hasMemberRelation.

So the triple would be

<http://localhost:8080/fcrepo/rest/68/6f/28/07/686f2807-f0cf-4459-8b4a-ea06ebcbd5e6> <http://pcdm.org/models#hasMember> <whatever is in proxyFor>

So if we add an object with RDF like:

@prefix pcdm: <http://pcdm.org/models#> .
@prefix ore: <http://www.openarchives.org/ore/terms/> .
 
<> a pcdm:Object ;
  ore:proxyFor <http://localhost:8080/fcrepo/rest/object1> .

Then our triple becomes <http://localhost:8080/fcrepo/rest/68/6f/28/07/686f2807-f0cf-4459-8b4a-ea06ebcbd5e6> <http://pcdm.org/models#hasMember> <http://localhost:8080/fcrepo/rest/object1>

We have added a pcdm:hasMember property to our Collection pointing to our Object Number 1, without touching either of them.

Let's try it.

return to top


Adding a member to a pcdm:Collection

To do this we will need the UUID for the collection and the resource.

  • Collection - f07c0d38-8290-4c2d-877c-233dfce374ea
  • Object - 4a51d7bc-83ed-4468-803a-17c411520bc0

Remember the pattern for this is http://localhost:8282/islandora/collection/<collection uuid>/member/<object uuid>

or

curl -i -XPOST http://localhost:8282/islandora/collection/f07c0d38-8290-4c2d-877c-233dfce374ea/member/4a51d7bc-83ed-4468-803a-17c411520bc0

The response will be about the creation of the proxy object and be a child of the members indirect container.

HTTP/1.1 201 Created
Date: Thu, 24 Mar 2016 03:47:50 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
ETag: "023bf18a79c3645040e4a06f7db0f8d62d701b51"
Cache-Control: private, must-revalidate
Last-Modified: Thu, 24 Mar 2016 03:47:51 GMT
Location: http://localhost:8282/fcrepo/rest/68/6f/28/07/686f2807-f0cf-4459-8b4a-ea06ebcbd5e6/members/1c/f2/93/58/1cf29358-fc4a-47c1-8b4c-9f0e199fc87f
Content-Length: 139
Connection: close
Content-Type: text/plain; charset=UTF-8

http://localhost:8282/fcrepo/rest/68/6f/28/07/686f2807-f0cf-4459-8b4a-ea06ebcbd5e6/members/1c/f2/93/58/1cf29358-fc4a-47c1-8b4c-9f0e199fc87f

Note: Location headers here are incorrect and need to be fixed.

Go back to your web browser and check out your members indirect container and its parent the pcdm:Collection.

The indirect container members now has a child object.

And the pcdm:Collection now has a pcdm:hasMember property to Object Number 1.

return to top


Deleting a member from a pcdm:Collection

If you remember the routes, you'll remember that this uses the same URL as adding a member. But we use the DELETE HTTP method.

So taking the URL from above and replacing POST with DELETE, we get.

curl -i -XDELETE http://localhost:8282/islandora/collection/f07c0d38-8290-4c2d-877c-233dfce374ea/member/4a51d7bc-83ed-4468-803a-17c411520bc0

and the result is

HTTP/1.1 204 No Content
Date: Thu, 24 Mar 2016 03:56:39 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Connection: close
Cache-Control: no-cache
Content-Length: 0
Content-Type: text/html

Done, no muss no fuss.

return to top

This is an archive. For new Tech Call notes, click here

⚠️ ARCHIVED Islandora Tech Calls

⚠️ ARCHIVED Islandora User Calls

Clone this wiki locally