= Apache OFBiz® plugin for REST

This initial implementation helps to expose existing or new OFBiz services as REST.
To facilitate this, added a new "action" attribute to service elements that helps to determine how a particular service can be accessed via REST.

== Important URLs
* API https://localhost:8443/rest
* WADL https://localhost:8443/rest/application.wadl
* OpenAPI docs https://localhost:8443/docs/swagger-ui.html

== Endpoints
Once deployed, following URLs can be accessed

* GET /rest/services
* GET /rest/services/{serviceName}?inParams=<URLEncodedJSON> 
* POST /rest/services/{serviceName} (For this endpoint, the service in parameters must be part of Request Body)

== Authentication
API is protected by JWT tokens, although other forms of access tokens may be supported in future.
An API client must first needs to authenticate itself using Basic Auth using username and password.
Username is nothing but OFBiz 'userLogin'. Token can also be generated using Swagger UI.
[source, json]
----
curl -X POST "https://localhost:8443/rest/auth/token" -H "accept: application/json" -H "Authorization: Basic YWRtaW46b2ZiaXo="
----
If successfully validated, generated token should be received in response
[source, json]
----
{
  "statusCode": 200,
  "statusDescription": "OK",
  "successMessage": "Token granted.",
  "data": {
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyTG9naW5JZCI6ImFkbWluIiwiaXNzIjoiQXBhY2hlT0ZCaXoiLCJleHAiOjE1OTY3MDk4MjAsImlhdCI6MTU5NjcwODAyMH0.9Hj4pkkeQowAMxPLrI_To0WTohxxgVR6FoViyx5HoboTACQZ4iqDyqiIBodkuCVsZwOTPT1RSAQJ0L_oSVMqBA",
    "token_type": "Bearer",
    "expires_in": "1800"
  }
}
----

Subsequent API calls must use received token using Bearer Authentication scheme as shown below -

[source, json]
----
GET /rest/services HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyTG9naW5JZCI6ImFkbWluIiwiaXNzIjoiQXBhY2hlT0ZCaXoiLCJleHAiOjE1OTY3MDk4MjAsImlhdCI6MTU5NjcwODAyMH0.9Hj4pkkeQowAMxPLrI_To0WTohxxgVR6FoViyx5HoboTACQZ4iqDyqiIBodkuCVsZwOTPT1RSAQJ0L_oSVMqBA
----

== Example

* List All Services (export="true" and verb = "get|post")
[source, json]
----
GET /rest/services HTTP/1.1
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJBcGFjaGVPRkJpeiIsImlhdCI6MTU0NzczOTM0OCwiZXhwIjoxNjc5Mjc1MzQ4LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiR2l2ZW5OYW1lIjoiSm9obm55IiwiU3VybmFtZSI6IlJvY2tldCIsIkVtYWlsIjoianJvY2tldEBleGFtcGxlLmNvbSIsInVzZXJMb2dpbklkIjoiYWRtaW4iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.fwafgrgpodBJcXxNTQdZknKeWKb3sDOsQrcR2vcRw97FznD6mkE79p10Tu7cqpUx7LiXuROUAnXEgqDice-BSg
----

Response :
[source, json]
----
{
  "statusCode" : 200,
  "statusDescription" : "OK",
  "successMessage" : "OK",
  "data" : [ {
    "name" : "findProductById",
    "description" : "Finds productId(s) corresponding to a product reference, productId or a GoodIdentification idValue",
    "link" : {
      "href" : "https://localhost:8443/rest/services/findProductById",
      "rel" : "self",
      "type" : "get"
    }
  }, {
    "name" : "searchProductsByGoodIdentificationValue",
    "description" : "Search Products by Good Identification Value",
    "link" : {
      "href" : "https://localhost:8443/rest/services/searchProductsByGoodIdentificationValue",
      "rel" : "self",
      "type" : "post"
    }
  } ]
}
----

* Call OFBiz service via GET(export="true" and verb = "get|post")


[source, json]
----
GET /rest/services/findProductById?inParams=%7B%22idToFind%22:%22GZ-1001%22%7D HTTP/1.1 +
Content-Type: application/json +
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJBcGFjaGVPRkJpeiIsImlhdCI6MTU0NzczOTM0OCwiZXhwIjoxNjc5Mjc1MzQ4LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiR2l2ZW5OYW1lIjoiSm9obm55IiwiU3VybmFtZSI6IlJvY2tldCIsIkVtYWlsIjoianJvY2tldEBleGFtcGxlLmNvbSIsInVzZXJMb2dpbklkIjoiYWRtaW4iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.fwafgrgpodBJcXxNTQdZknKeWKb3sDOsQrcR2vcRw97FznD6mkE79p10Tu7cqpUx7LiXuROUAnXEgqDice-BSg
----

Response :
[source, json]
----
{
  "statusCode" : 200,
  "statusDescription" : "OK",
  "data" : {
    "product" : {
      "createdStamp" : "2020-06-11T15:29:58.182+0000",
      "productName" : "Nan Gizmo",
      "createdByUserLogin" : "admin",
      "productId" : "GZ-1001",
      "taxable" : "Y",
      "primaryProductCategoryId" : "101",
      "createdTxStamp" : "2020-06-11T15:29:57.523+0000",
      "lastUpdatedTxStamp" : "2020-06-11T15:29:57.523+0000",
      "isVirtual" : "N",
      "autoCreateKeywords" : "Y",
      "description" : "Indian style Nan gizmo",
      "chargeShipping" : "Y",
      "internalName" : "Nan Gizmo",
      "lastModifiedByUserLogin" : "admin",
      "lastUpdatedStamp" : "2020-06-11T15:29:58.182+0000",
      "lastModifiedDate" : "2001-05-13T06:30:00.000+0000",
      "productTypeId" : "FINISHED_GOOD",
      "createdDate" : "2001-05-13T06:30:00.000+0000",
      "isVariant" : "N"
    }
  }
}
----

* Call OFBiz Service via POST +
[source, json]
----
POST rest/services/searchProductsByGoodIdentificationValue HTTP/1.1
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJBcGFjaGVPRkJpeiIsImlhdCI6MTU0NzczOTM0OCwiZXhwIjoxNjc5Mjc1MzQ4LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiR2l2ZW5OYW1lIjoiSm9obm55IiwiU3VybmFtZSI6IlJvY2tldCIsIkVtYWlsIjoianJvY2tldEBleGFtcGxlLmNvbSIsInVzZXJMb2dpbklkIjoiYWRtaW4iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.fwafgrgpodBJcXxNTQdZknKeWKb3sDOsQrcR2vcRw97FznD6mkE79p10Tu7cqpUx7LiXuROUAnXEgqDice-BSg
{
    "idFragment": "2644"
}
----

Response +
[source, json]
----
{
  "statusCode" : 200,
  "statusDescription" : "OK",
  "data" : {
    "products" : [ {
      "internalName" : "Round Gizmo",
      "productId" : "GZ-2644",
      "primaryProductCategoryId" : "101",
      "isVariant" : "N",
      "goodIdentificationTypeId" : "INVOICE_EXPORT",
      "idValue" : "GZ-2644-replaced",
      "isVirtual" : "N"
    } ]
  }
}
----
