REST / HTTP methods: POST vs. PUT vs. PATCH

 Each HTTP request consists of a method (sometimes called verb) that indicates the action to be performed on the identified resource.

When building RESTful Web-Services the HTTP method POST is typically used for resource creation while PUT is used for resource updates. While this is fine in most cases it can be also viable to use PUT for resource creation. PATCH is an alternative for resource updates as it allows partial updates.

In general we can say:

  • POST requests create child resources at a server defined URI. POST is also used as general processing operation
  • PUT requests create or replace the resource at the client defined URI
  • PATCH requests update parts of the resource at the client defined URI

But let's look a bit more into details and see how these verbs are defined in the HTTP specification. The relevant part here is section 9 of the HTTP RFC (2616).

POST - "Create new"

The RFC describes the function of POST as:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

This allows the client to create resources without knowing the URI for the new resource. For example, we can send a POST request to /projects to create a new project. The server can now create the project as a new subordinate of /project, for example: /projects/123. So when using POST for resource creation the server can decide the URI (and typically the ID) of the newly created resources.

When the server created a resource, it should respond with the 201 (Created) status code and a Location header that points to the newly created resource.

For example:

Request:

POST /projects HTTP/1.1
Content-Type: application/json

{
    "name": "my cool project",
    ...
}

Response:

HTTP/1.1 201 Created
Location: https://cool.api.com/projects/123

POST is not idempotent. So sending the same POST requests multiple times can result in the creation of multiple resources. Depending on your needs this might be a useful feature. If not, you should have some validation in place and make sure a resource is only created once based on some custom criteria (e.g. the project name has to be unique).

The RFC also tells us:

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

This means that POST does not necessarily need to create resources. It can also be used to perform a generic action (e.g. starting a batch job, importing data or process something).

PUT - "Update existing if exists"

The main difference between POST and PUT is a different meaning of the request URI. The HTTP RFC says:

The URI in a POST request identifies the resource that will handle the enclosed entity. [..] In contrast, the URI in a PUT request identifies the entity enclosed with the request [..] and the server MUST NOT attempt to apply the request to some other resource.

For PUT requests the client needs to know the exact URI of the resource. We cannot send a PUT request to /projects and expect a new resource to be created at /projects/123. Instead, we have to send the PUT request directly to /projects/123. So if we want to create resources with PUT, the client needs to know (how to generate) the URI / ID of the new resource.

In situations where the client is able to generate the resource URI / ID for new resources, PUT should actually be preferred over POST. In these cases the resource creation is typically idempotent, which is a clear hint towards PUT.

It is fine to use PUT for creation and updating resources. So sending a PUT request to /projects/123 might create the project if it does not exist or replace the existing project. HTTP status codes should be used to inform the client if the resource has been created or updated.

The HTTP RFC tells us:

If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.

Generally speaking, if the exact resource URI is known and the operation is idemponent, PUT is typically a better choice than POST. In most situations this makes PUT a good choice for update requests.

However, there is one quirk that should be remembered for resource updates. According to the RFC, PUT should replace the existing resource with the new one. This means we cannot do partial updates. So, if we want to update a single field of the resource, we have to send a PUT request containing the complete resource.

PATCH - "Partial updates"

The HTTP PATCH method is defined in RFC 5789 as an extension to the earlier mentioned HTTP RFC. While PUT is used to replace an existing resource, PATCH is used to apply partial modifications to a resource.

Quoting the RFC:

With PATCH, [..], the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version.  The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources;

So PATCH, similar to POST, might also affect resources other than the one identified by the Request URI.

Often PATCH requests use the same format as the resource that should be updated and just omit the fields that should not change. However, it does not have to be this way. It is also fine to use a separate patch format, which describes how the resource should be modified.

PATCH is neither safe nor idempotent.

Maybe you are wondering in which situations a partial resource update is not idempotent. A simple example here is the addition of an item to an existing list resource, like adding a product to a shopping cart. Multiple (partial) update requests might add the product multiple times to the shopping cart.

More detailed information about the usage of PATCH can be found in my post about partial updates with PATCH.

SOAP vs. REST: The Differences and Benefits

 

Defining SOAP and REST

SOAP (Simple Object Access Protocol) and REST (Representational State Transfer) are both web service communication protocols. SOAP was long the standard approach to web service interfaces, although it’s been dominated by REST in recent years, with REST now representing more than 70% of public APIs.  Understand the primary differences between SOAP vs. REST  and how each can benefit your organization’s goals.

SOAP vs REST: Primary Differences

REST operates through a solitary, consistent interface to access named resources. It’s most commonly used when you’re exposing a public API over the Internet. SOAP, on the other hand, exposes components of application logic as services rather than data. Additionally, it operates through different interfaces. To put it simply, REST accesses data while SOAP performs operations through a more standardized set of messaging patterns. Still, in most cases, either REST or SOAP could be used to achieve the same outcome (and both are infinitely scalable), with some differences in how you’d configure it.

SOAP was originally created by Microsoft, and it’s been around a lot longer than REST. This gives it the advantage of being an established, legacy protocol. But REST has been around for a good time now as well. Plus, it entered the scene as a way to access web services in a much simpler way than possible with SOAP by using HTTP.

Benefits of REST Over SOAP

In addition to using HTTP for simplicity, REST offers a number of other benefits over SOAP:

  • REST allows a greater variety of data formats, whereas SOAP only allows XML.
  • Coupled with JSON (which typically works better with data and offers faster parsing), REST is generally considered easier to work with.
  • Thanks to JSON, REST offers better support for browser clients.
  • REST provides superior performance, particularly through caching for information that’s not altered and not dynamic.
  • It is the protocol used most often for major services such as Yahoo, Ebay, Amazon, and even Google.
  • REST is generally faster and uses less bandwidth. It’s also easier to integrate with existing websites with no need to refactor site infrastructure. This enables developers to work faster rather than spend time rewriting a site from scratch. Instead, they can simply add additional functionality.

Still, SOAP remains the preferred protocol for certain use cases. The general consensus among experts these days is that REST is the typically preferred protocol unless there’s a compelling reason to use SOAP (and there are some cases in which SOAP is preferred).

Benefits of SOAP Over REST

Because you can achieve most outcomes using either protocol, it’s sometimes a matter of personal preference. However, there are some use cases that SOAP tends to be better-suited for. For instance, if you need more robust security, SOAP’s support for WS-Security can come in handy. It offers some additional assurances for data privacy and integrity. It also provides support for identity verification through intermediaries rather than just point-to-point, as provided by SSL (which is supported by both SOAP and REST).

Another advantage of SOAP is that it offers built-in retry logic to compensate for failed communications. REST, on the other hand, doesn’t have a built-in messaging system. If a communication fails, the client has to deal with it by retrying. There’s also no standard set of rules for REST. This means that both parties (the service and the consumer) need to understand both content and context.

Other benefits of SOAP include:

  • SOAP’s standard HTTP protocol makes it easier for it to operate across firewalls and proxies without modifications to the SOAP protocol itself. But, because it uses the complex XML format, it tends to be slower compared to middleware such as ICE and COBRA.
  • Additionally, while it’s rarely needed, some use cases require greater transactional reliability than what can be achieved with HTTP (which limits REST in this capacity). If you need ACID-compliant transactions, SOAP is the way to go.
  • In some cases, designing SOAP services can actually be less complex compared to REST. For web services that support complex operations, requiring content and context to be maintained, designing a SOAP service requires less coding in the application layer for transactions, security, trust, and other elements.
  • SOAP is highly extensible through other protocols and technologies. In addition to WS-Security, SOAP supports WS-Addressing, WS-Coordination, WS-ReliableMessaging, and a host of other web services standards, a full list of which you can find on W3C.

At the end of the day, the best protocol is the one that makes the most sense for the organization, the types of clients that you need to support, and what you need in terms of flexibility. Most new APIs are built using REST and JSON, simply because it typically consumes less bandwidth and is easier to understand both for developers implementing initial APIs as well as other developers who may write other services against it. Because it’s more easily consumed by most of today’s web browsers, REST+JSON has become the defacto technology for the majority of public APIs. However, SOAP remains a valuable protocol in some circumstances. Plus, you don’t have to look far to find die-hard fans advocating for SOAP for certain use cases.

JSON Decoding Examples - IB REST Services

 First we will look at a simple REST JSON Post. The screenshot below has the service operation setup. This is the most simple web service. You will notice that:

  • There is no Template other than /
  • There is no Document Template because we are not passing any parameters
  • The Request and Response Message objects are both CHG_GENERIC.V1 which is a “Nonrowset-based” based messages. This is is not shown.
Service Operation Setup

We plan on posting some simple JSON to this. The HTTP Signature will look like this:

POST http://localhost:8000/PSIGW/RESTListeningConnector/PSFT_CS/CHG_JSON_TEST.v1/
Authorization: Basic UFM6dHJ5aW5nLXNlZS1pZi1JLXBvc3RlZC1teS1wYXNzd29yZC1JLXNlZQ==
Content-Type: application/json

{
   "firstName": "Chris",
   "lastName": "Malek",
   "Region": "Southern California",
   "FavoriteDesert": "Pie, any kind"
}

The response that comes out of this web services the following.

HTTP/1.1 200 OK
Connection: close
Date: Wed, 02 Dec 2020 04:33:21 GMT
Content-Length: 234
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
Set-Cookie: JSESSIONID=6zshuetDLvmVT5G55VCUt0su3nVWAn469hsagTQOqg0zHVExziNa!-1985259815; path=/; HttpOnly,psmap=; domain=.c.peoplesoftdemo-1470578694381.internal; path=/

{

  "firstName": "Chris",
  "lastName": "Malek",
  "Region": "Southern California",
  "FavoriteDesert": "Pie, any kind",
  "META": {

    "OPRID": "PS",
    "CURRENT_TIME": "2020-12-02 04:33:21.000000",
    "TRANSACTION_ID": "81fa5f4b-3457-11eb-9b6b-e783fa52141b",
    "DBNAME": "CS92U009"
  }
}

The handler parses the inbound root JSON object strings and echos any value back out. We also add a “META” object with some information about the run-time environment.

The entire PeopleCode handler for this web service is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import PS_PT:Integration:IRequestHandler;

class simpleJSONPost implements PS_PT:Integration:IRequestHandler
   method onRequest(&msRequest As Message) Returns Message;
   
end-class;

method onRequest
   /+ &msRequest as Message +/
   /+ Returns Message +/
   /+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
   
   
   Local Message &response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
   
   Local JsonObject &responseRootJSON = CreateJsonObject();
   
   Local string &requestPayload = &msRequest.GetContentString();
   
   Local JsonParser &parser = CreateJsonParser();
   
   Local boolean &bParseResult = &parser.Parse(&requestPayload);
   
   If &bParseResult = True Then
      Local integer &i;
      
      Local JsonObject &jObj = &parser.GetRootObject();
      For &i = 1 To &jObj.ChildCount
         
         Local string &propName;
         
         &propName = &jObj.GetPropertyNameAt(&i);
         &responseRootJSON.AddProperty(&propName, &jObj.GetAsString(&propName));
         
      End-For;
   End-If;
   
   
   Local JsonObject &JsonObjMETA = CreateJsonObject();
   
   &JsonObjMETA.AddProperty("OPRID", %OperatorId);
   &JsonObjMETA.AddProperty("CURRENT_TIME", %Datetime);
   &JsonObjMETA.AddProperty("TRANSACTION_ID", &msRequest.TransactionId);
   &JsonObjMETA.AddProperty("DBNAME", %DbName);
   
   &responseRootJSON.AddJsonObject("META", &JsonObjMETA);
   
   
   /* Push the generated XML to the response document */
   If &response.SetContentString(&responseRootJSON.ToString()) Then
      
   End-If;
   Return &response;
   
end-method;

With this simple example you can see:

  • How to get the raw unparsed JSON string from the request message
  • Parse a simple JSON object
  • Return back JSON data

This web service has no:

  • Error Handling
  • JSON detection of different data types
  • Any real practical use

Integration Gateway Error Handling

In general, exceptions are thrown in a target connector and caught by a listening connector. As a result, a listening connector must catch these exceptions and handle them as appropriate. Typically, the listening connector generates an error message and sends it back to the requester.

Standard Exceptions

The following standard error and exception types are handled by the integration gateway, target connectors, and listening connectors:

Exception Type

Description

DuplicateMessageException

A target connector attempted to process a message that has already been processed. This is usually discovered based on an error that is attained from the external system that is being contacted.

Of the connectors that are delivered with the PeopleSoft software, only the PeopleSoft 8.1 target connector (PSFT81TARGET) can generate this exception. Target connectors are not required to generate this exception.

ExternalApplicationException

The message reached its intended destination but could not be processed.

Determining that the destination could not process a message requires significant knowledge of the destination system, which a target connector might not have. Whenever possible, a target connector should attempt to determine this situation; otherwise this task must be decentralized and handled outside of the integration gateway.

For example, the HTTP target connector (HTTPTARGET) generates this exception when the external system returns an HTTP system code of 500.

ExternalSystemContactException

The target connector cannot establish a connection with the intended destination. This is one of the most common exceptions.

When this exception is thrown during an asynchronous transaction, PeopleSoft Integration Broker tries to resend the message until successful.

GeneralFrameworkException

A general error occurred.

InvalidMessageException

A connector or the gateway manager determined that the message cannot be processed because of missing or erroneous information in a request or response.

MessageMarshallingException

A gateway service’s attempt to get information from an IBRequest or IBResponse failed. This can occur when the gateway services attempt to access a content section of a document by using an out-of-range index from one of the following methods:

  • GetContentSectionAt(index)

  • GetContentSectionInfoAt(index)

  • RemoveContentSectionAt(index)

If you try to access IBRequest or IBResponse with an out-of-range index by using any of these methods, this exception is thrown automatically and processing is interrupted.

MessageUnmarshallingException

A gateway service’s attempt to build an IBRequest or IBResponse failed. Failure can occur when:

  • Instantiating an IBRequest or IBResponse from a Multipurpose Internet Mail Extensions (MIME) format where the message that was sent does not comply with the PeopleSoft MIME format.

  • Instantiating an IBRequest by using the PS_XML format and passing an invalid PS_XML message.

    This is typically from the HTTP listening connector.

  • Setting invalid values to methods, such as setTransactionID or setMessageType.

These failures cause the integration gateway to generate this exception automatically and processing is interrupted.

Java Exceptions

Target connectors and listening connectors can handle miscellaneous Java exceptions, such as NullPointerException and ArrayOutOfBoundsException.

Use the Handler Tester utility to debug service operation handler PeopleCode.

The Handler Tester utility enables you to use the PeopleSoft Pure Internet Architecture to test any of the following handler types:

  • OnSend.

  • OnRequest

  • OnRouteReceive

  • OnRouteSend.

  • OnAckReceive

  • OnNotify.


Use this table to handle common issues in PeopleSoft Integration Broker:

Area or Suspected Issue

Debugging Suggestion

Application server exceptions.

Check the application server log:

<PS_CFG_HOME>\appserv\<Domain>\LOGS\ appsrv.log

Message handlers are not running.

Check the application server domain status or queue status in the PeopleSoft Application Server Administration menu (PSAdmin). Select Domain Status, Server Status or Domain Status, Queue Status.

Integration gateway.

Check the integrationGateway.properties file and verify the property settings.

The default file location is <PIA_HOME>\webserv\<DOMAIN>\applications\peoplesoft\PSIGW.war.war\WEB-INF\integrationGateway.properties.

Integration gateway.

Check the integration gateway message log.

The default file location is <PIA_HOME>\webserv\<DOMAIN>\applications\peoplesoft\PSIGW.war.war\msgLog.html.

Queues are paused.

Check the Service Operations Monitor. Select PeopleTools > Integration Broker > Service Operations Monitor > Administration > Queue Status.

A node is paused.

Check the Service Operations Monitor. Select PeopleTools > Integration Broker > Service Operations Monitor > Administration > Node Status.

Incorrect gateway uniform resource locator (URL).

Check the Gateways component to verify that the integration gateway URL is correct. Select PeopleTools > Integration Broker > Configuration > Gateways.

Node inactive.

Check the node definition. Select PeopleTools > Integration Broker > Integration Setup > Nodes.

Subscription PeopleCode is missing or incorrect.

Check the Service Operations Monitor. Select PeopleTools > Integration Broker > Monitoring > Asynchronous Services > Subscription Contracts.

A service operation is inactive.

Check the service operation definition in the PeopleSoft Pure Internet Architecture. Select PeopleTools > Integration Broker > Integration Setup > Service Operations.

There are transform problems.

  • Check the Application Engine object in PeopleSoft Application Designer.

  • For before and after images, check the Service Operations Monitor.

    For asynchronous service operations, select PeopleTools > Integration Broker > Service Operations Monitor > Monitoring > Asynchronous Details. Click the View XML link for the publication contract or subscription contract.

    For synchronous service operations, select PeopleTools > Integration Broker > Service Operations Monitor > Monitoring > Synchronous Details. Use the Log Type drop-down list box to select Request Transformed or Response Transformed, and then click View XML.

  • Verify that the TraceAE flag in the following directory equals 8192:

    <PS_CFG_HOME>\appserv\<Domain>\psappsrv.cfg

    Setting the TraceAE flag in the psappsrv.cfg file instructs the application server to generate a transformation trace log with the .aet extension, written to the following directory:

    <PS_CFG_HOME>\appserv\<Domain>\LOGS\ <operID>_<machine name>.AET

    The log file contains:

    • The original XML structure as it entered the transformation engine.

    • The output of the XML as it passed through each step of the transform program.

Integration Broker security

Set the application server logging level to 4 or greater to capture information related to the following situations:

  • No routing at source node.

  • No routing at target node.

  • User invoking a service operation has different permissions than specified on the service operation on the source node.

  • No node password found on source node.

  • No node password found on target node.

  • Mismatched node password on source and target nodes.

  • No permissions set for the service operation on the source node.


PeopleCode to retrieve Google map between two addresses

  PeopleCode Example: /* Define constants for the API request */ Local string &origin = "123 Main St, Anytown, USA";   /* ...