Chris Malek is a PeopleToolsยฎ Technical Consultant with two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.
About Chris Work with ChrisIntroducing a small but powerful PeopleSoft bolt-on that makes web services very easy. If you have a SQL statement, you can turn that into a web service in PeopleSoft in a few minutes.
In REST, PeopleTools gives you some but not all control over the HTTP Status codes. In the REST paradigm, the status codes should be meaningful. Unfortunately, the PeopleTools REST does not give you complete control over the status codes. There is much left to be desired in this corner of the framework. You have to make some compromises on what you can return and the actual structure of your code. You will see many instance of this tag throughout this section Death by a thousand cuts! ๐.
If you need to have complete control over the status code, I would suggest that you use a custom response value or header. If you have a proxy server or API gateway in front of your integration broker, then you can use that to translate the status codes to the client.
There are a few different “classes” of HTTP response codes. Let’s briefly go over them and talk about what is supported in the framework. There is a great Wikipedia document on status code
HTTP Status Class | Usage | Supported in PeopleTools |
---|---|---|
1xx | Information was received | No ๐ |
2xx | Success | Yes some values are supported ๐. Use the HTTPResponseCode property on your response message . |
3xx | Redirection | No ๐ |
4xx | Client Error | Some support but you have to “tie your code in knots” and be on a recent tools release. ๐ฐ Use the OnErrorHttpResponseCode which is derived from the PS_PT:Integration:IRequestHandler interface. |
5xx | Server Error | No support in the handler but PeopleTools may send 500 errors if certain errors occur prior to getting to your handler code. ๐ |
We will look below at how to use the supported values and how you have to setup your service operation and structure your code.
For the examples in this section, I have configured a very basic service operation with no parameters. It looks like this:
A few things to note:
{
"guid": "3761af35-d646-455d-8fb9-37ef3b908ed8"
}
The base PeopleCode handler looks like the following.
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 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;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
The HTTP signature to call this service is:
|
|
|
|
As we progress through this section, we will change the service operation as well as the handler to see how the HTTP status codes work.
In order to support different 2xx status codes you have to “whitelist” the code on the service operation setup. You do this on the service operation by inserting rows into the “Optional Status Codes” subpage.
You can insert values into the grid and PeopleTools limits the ones you can insert. You cannot set any response status code that is not whitelisted. If you try there will be a server failure. We will see this below.
The only values supported are:
What happens if I try to set a response code that is NOT whitelisted? Let’s find out. If we take all the setup we have in the base service operation above but just add one line to the PeopleCode handler to try to return 202
.
The last 2 lines of the handler look like this now:
/* New piece of code to setup response code */
&response.HTTPResponseCode = 202;
Return &response;
end-method;
The response that comes back from the handler is the following:
|
|
There are a few ugly things about this:
HTTP/1.1 200 OK
was returned. ๐ This is not correct but we have zero control here.
5XX
status code here because this is configuration on the server.Http Response Code 202 was not found on Service Operation Definition CHG_STATUS_TEST_GET
If you noticed in the base service operation configuration example, we had setup the service operation with a 200 OK
to be the default HTTP status code returned. Our handler ran to success and returned a JSON document. The framework returned 200 OK
and our handler code did not have to do anything special in regard to the status code. The default was used.
This is how you will configure most of your service operations. For 200, you do not need to do anything in your handler code.
This is only available on a POST Method.
Wikipedia has the following definition for 201.
This is a good status code to return when you have created a new resource. This is generally used in a POST request where you are creating a new resource. Some HTTP clients may expect a 201
status code when they POST data to a service.
Wikipedia has the following definition for 202.
This might be appropriate for web services where the handler kicked off a batch job that will process in the future or maybe stored some data in a staging table that will be processed later.
Above we tried to set the 202
response without actually whitelisting the value. We will now actually whitelist the 202 value and try to set it like we did above with &response.HTTPResponseCode = 202;
We add the white list.
We set the response code:
&response.HTTPResponseCode = 202;
When we call the service we get back this response:
|
|
Wikipedia has the following definition for 203.
I have not seen a use case for this in a production PeopleSoft setup. If PeopleSoft is serving as a front end proxy for another service or batch process this might be useful.
Let’s whitelist the 203
code and change our handler.
The handler code now becomes:
&response.HTTPResponseCode = 203;
The HTTP response is:
HTTP/1.1 203 Non-Authoritative Information
Connection: close
Date: Thu, 07 Nov 2019 18:23:34 GMT
Content-Length: 72
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
{
"guid": "0d6cf692-9b01-4272-92da-ca78547141a9"
}
Wikipedia has the following definition for 204.
This is a status code that tells the client that there should be nothing in the the body to look at but everything else was good. This is generally more applicable to a POST request where a client may be posting something to the server and may not need a response back other than an acknowledgement that the payload was accepted.
In our code below we are going to use it in a GET situation which does not make complete sense but it will show some interesting points.
Let’s whitelist the 204
code and change our handler.
The handler code now becomes:
&response.HTTPResponseCode = 204;
The handler code from the base example has not changed. We are still setting the JSON body. However, we see in the response below that the PeopleTools framework actually stripped out the body that our handler set. This is both expected and unexpected. I wanted to point this out as if you set this accidentally in your code and your client is expecting a response you could run into issues.
The HTTP response is:
HTTP/1.1 204 No Content
Connection: close
Date: Thu, 07 Nov 2019 18:27:08 GMT
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
Wikipedia has the following definition for 205.
In our code below we are going to use it in a GET situation which does not make complete sense but it will show some interesting points.
Let’s whitelist the 205
code and change our handler.
The handler code now becomes:
&response.HTTPResponseCode = 205;
The HTTP response is:
HTTP/1.1 205 Reset Content
Connection: close
Date: Thu, 07 Nov 2019 18:33:48 GMT
Content-Length: 73
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
{
"guid": "cda5ac28-f0f0-47a5-ba0e-7823ee18fdf0"
}
You will see that we got the 205 response and the JSON body.
Wikipedia has the following definition for 206.
This is a good HTTP status code for a web service that supports pagination and the full data is not returned.
Let’s whitelist the 206
code and change our handler.
The handler code now becomes:
&response.HTTPResponseCode = 206;
The HTTP response is:
HTTP/1.1 206 Partial Content
Connection: close
Date: Thu, 07 Nov 2019 18:37:51 GMT
Content-Length: 73
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
{
"guid": "ac3d9761-fafa-452d-b91b-2057cb3caa14"
}
Wikipedia has the following definition for 207.
I can see this being used in PeopleSoft when your handler class several different component interfaces and some of them may have been successful and other may have failed. You will have to return some encoded response with those status codes and the client will have to parse and take appropriate action.
Let’s whitelist the 207
code and change our handler.
The handler code now becomes:
&response.HTTPResponseCode = 207;
The HTTP response is:
HTTP/1.1 207 Unknown
Connection: close
Date: Thu, 07 Nov 2019 18:38:43 GMT
Content-Length: 73
Content-Type: application/json; encoding="UTF-8"
Content-Encoding: gzip
{
"guid": "b2903976-6c1e-458d-a532-dffae5cfa7d9"
}
The interesting thing here is that the text string that PeopleTools returned was HTTP/1.1 207 Unknown
instead of HTTP/1.1 207 Multi-Status
Welcome to PeopleTools! Death by a thousand cuts! ๐
The 4xx class of errors are a bit different than the 2xx class. This is where you have to tie yourself in knots a bit to support these 4xx errors. You cannot send back 4xx errors from the main handler. This is actually extremely limiting and very disappointing. As we saw in the sections above, you can only set values on the HTTPResponseCode
response messages that are whitelisted and only 2xx codes are allowed on the service operation setup.
So how do you return 4xx errors? First we need to add a “Fault type” message using the button on the Service Operation Setup.
We will configure the fault message to use our same “generic” message which is a non-rowset message because we want to control the output in the PeopleCode. Additionally, we set the status code to 400 and the content type to JSON.
Now we need to make some changes to our handler. Specifically, we need to add an onError
method that will actually handle any errors that are thrown. It is in this method where you can set 4xx class errors but you do it differently than you do the 2xx class errors. If you do not implement this method in your handler the framework will return an error for you and for a “robust” and well designed API running in production this is probably not what you want.
Let’s look at a fully expanded handler.
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
/* force an error - This will jump to the OnEror Method */
throw CreateException( - 1, - 1, "fake error thrown");
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Local string &responseErrorString;
Local Exception &exception = &msRequest.IBException;
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("error", &exception.ToString());
&responseErrorString = &rootJSON.ToString();
Return &responseErrorString;
end-method;
There is a subtle difference between the response signature for onRequest
and the onError
onRequest
- returns a message
object.
onError
- Returns a string
.
message
so there is no way to set HTTP custom headers. This is very limiting and frustrating. Death by a thousand cuts! ๐This is frustrating if you want to use the “magic” of PeopleSoft rowsets to return data. They do not work the same in the onError. You have to generally re-implement the encoding logic and return it as a string. Death by a thousand cuts! ๐
If you look at all synchronous handlers you will see that they implement an interface. That is seen in this statement: implements PS_PT:Integration:IRequestHandler
. If you open up that class you will see that methods and properties that are on the interface. There have been some small changes in recent tools release to support REST 4XX status codes. Specifically, these two properties were added to to interface.
property integer OnErrorHttpResponseCode;
- You use this to return a whitelist 4xx class status code.property string OnErrorContentType;
- You use this to tell the IB framework what content encoding is in the response string of OnError. These have to be whitelisted as well.The thing that is not quite apparent is how errors in the OnRequest
method get pushed to the onError
method. Here is a screenshot that shows that any uncaught exception in the onRequest
“jumps” to the onError
. If you don’t implement the onError
in your handler the system will return a response for you. However, you generally do not want that. I generally wrap 99% of the code in the onRequest
with a try / catch
block to avoid the onError
method kicking in. However, if you want to support one of these supported 4xx status codes, then you have to return a response from the onError
method and NOT your onRequest
method. (You may want to read that a few times to make sure you understand it.)
You have a limited set of 4xx errors that can be whitelisted.
The only allowed 4xx class errors are the following.
We will go through each one below and see what they return and also find some issues.
In the section directly above, we added a Fault type message and set the status code to 400
and the Content-Type
to application/json
. These are the default values. If we take that revised handler above that implements the OnError
method and has the fake error embedded, we will see that we do not have to do anything special to get PeopleTools to return the default 400
status code.
The HTTP response is:
HTTP/1.1 400 Bad Request
Connection: close
Date: Thu, 07 Nov 2019 19:48:25 GMT
Content-Length: 152
Content-Type: application/json; encoding="UTF-8"
X-ORACLE-DMS-ECID: fc854e66-fb35-42cf-b0b2-0beabf4f0f46-00000029
Content-Encoding: gzip
X-ORACLE-DMS-RID: 0
{
"error": "fake error thrown (-1,-1) CHG_BOOK_SAMPLES.handlers.statusCodeExampe1.OnExecute Name:onRequest PCPC:552 Statement:8 (-1,-1)"
}
The 403 Forbidden
error message might be a great place to actually return an error code when a user does not have access to the given data. This can be data security like row level security or maybe component interface security. They may have access to the web service but something they are requesting inside that service is not available to them.
I really wish you could return this inside the main onRequest
handler. This is where I see we have to tie ourselves in knots or just be creative in how we structure out code (more on that in the sections below)
Let’s look at how we return the 403 error code.
We need to ensure we have whitelisted that code.
Then we change our handler to set the 403 status code.
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Local string &responseErrorString;
Local Exception &exception = &msRequest.IBException;
Local JsonObject &rootJSON = CreateJsonObject();
&rootJSON.AddProperty("error", &exception.ToString());
&responseErrorString = &rootJSON.ToString();
%This.OnErrorHttpResponseCode = 403;
Return &responseErrorString;
end-method;
The response we get in this scenario is not what is expected. We set a JSON string have have JSON as the default error content type. However, we are getting and HTML response and the PeopleTools framework is escaping our JSON. Death by a thousand cuts! ๐
|
|
This seems to be a bug with the handling of 403
.
The 404 Not Found
is a great status when the client asks for a resource that is not there.
Let’s go ahead and just whitelist all the remaining 4xx code so we don’t have to do it below.
Now if we change our line in the onError
method to the following:
%This.OnErrorHttpResponseCode = 404;
Now we can test this and see if we have the same issues as the 404.
|
|
We see above that the 404 worked as expected and JSON was returned.
We will just test each of the following by just changing the value we set on the OnErrorHttpResponseCode
property. In this case we set.
%This.OnErrorHttpResponseCode = 405;
|
|
%This.OnErrorHttpResponseCode = 406;
|
|
%This.OnErrorHttpResponseCode = 409;
|
|
%This.OnErrorHttpResponseCode = 411;
|
|
%This.OnErrorHttpResponseCode = 412;
|
|
%This.OnErrorHttpResponseCode = 415;
|
|
%This.OnErrorHttpResponseCode = 417;
|
|
In the code examples so far, we were actually setting the HTTP response codes for the 4xx class and the response string in the onError
method. However, this can be inconvenient. It probably makes more sense for you to set some class instance variables in your onRequest
method which sets up a structured error response, sets the status code, and sets the response content type. You would think that we can do that since the OnErrorHttpResponseCode
and OnErrorContentType
properties exist on the class and can be set anywhere in the class. However, we will see below that it is not possible and the reason is obscured in the “blackbox” PeopleTools code. It seems properties and instance variables on your handler class are not accessible in the onError
method (Death by a thousand cuts! ๐) This seems like some sort of PeopleTools bug to me. We will look at a few examples below and recommend a structure to work within the issues in the framework.
First let’s try to do something rather sensible and make use of instance properties to set the JSON error message in the OnRequest
method and also try to set the 404 status code. Then in the onError
method we just reference that rootJSON
property to return the JSON generated above. However, this does NOT work.
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
property JsonObject rootJSON;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
&rootJSON = CreateJsonObject();
&rootJSON.AddProperty("error", "The object you request does not exists.");
/* Fake a 404 Error */
%This.OnErrorHttpResponseCode = 404;
/* force an error - This will jump to the OnEror Method */
throw CreateException( - 1, - 1, "fake error thrown");
/* ------- */
/* No code below here will run because of the throw above */
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Return &rootJSON.ToString();
end-method;
When you try to run this code you get a 200 status code back and HTML. There is something strange here where the OnError
did not accept the value we set with %This.OnErrorHttpResponseCode = 404
. And the reference to the class property rootJSON
did not seem to work either. This is very frustrating!
|
|
Next we need to shift things around a bit and try to reverse engineer what is happening and how we can get this to work. We need some way of setting some variables that can be picked up in the onError
method. The onRequest
method code probably knows best if a 404 Not Found
or 403 Forbidden
should be given. We need to restructure out code a bit to make this work. This is not ideal but you have to work within the bound of the framework, warts and all.
Here is the second attempt. This actually still does NOT work as we will see. Death by a thousand cuts! ๐
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
property JsonObject rootJSON;
private
instance integer &ResponseStatusCode;
instance string &errorMessage;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
&rootJSON = CreateJsonObject();
/* Fake a 404 Error */
&ResponseStatusCode = 404;
&errorMessage = "The resource you requested does not exist.";
/* force an error - This will jump to the OnEror Method */
throw CreateException( - 1, - 1, "fake error thrown");
/* ------- */
/* No code below here will run because of the throw above */
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
%This.OnErrorHttpResponseCode = &ResponseStatusCode;
Local JsonObject &rootJSONError = CreateJsonObject();
&rootJSONError.AddProperty("error", &errorMessage);
Return &rootJSONError.ToString()
end-method;
OnErrorHttpResponseCode
property using the instance variable set on the onRequest
&errorMessage
instance variable.When you run this, any reasonable developer would expect that this would return a 404 status with a JSON error of The resource you requested does not exist.
. However, you would be very wrong to assume this.
What we actually get back below is:
error
JSON property is blank.
|
|
What does this tell us? Either that:
PS_PT:Integration:IRequestHandler
implementation are NOT accessible.onError
was triggered.
This is again very lame and it is endless issues like this where I can see a developer giving up and going back to a flat file integration. However, since we are writing a book about web services we must press on.
Let’s try to change the instance variables to properties instead. The only thing we change is lines 10 and 11.
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
property JsonObject rootJSON;
property integer ResponseStatusCode;
property string errorMessage;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
&rootJSON = CreateJsonObject();
/* Fake a 404 Error */
&ResponseStatusCode = 404;
&errorMessage = "The resource you requested does not exist.";
/* force an error - This will jump to the OnEror Method */
throw CreateException( - 1, - 1, "fake error thrown");
/* ------- */
/* No code below here will run because of the throw above */
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
%This.OnErrorHttpResponseCode = &ResponseStatusCode;
Local JsonObject &rootJSONError = CreateJsonObject();
&rootJSONError.AddProperty("error", &errorMessage);
Return &rootJSONError.ToString()
end-method;
The response is the same with using properties and instance variables. (Bang your head against the wall a few times.) This is very frustrating ๐ .
|
|
Global variable may work but I try to avoid those as all costs as they can have very unexpected consequences. Let’s see if we can somehow use data on the Exception
that we throw
.
Let’s revise our handler to pass the HTTP Status code as the message number and embed the error message in the text. Of course, we could define a real message catalog for this but I want to make this example simple. We make a few small changes below:
import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
property JsonObject rootJSON;
private
instance integer &ResponseStatusCode;
instance string &errorMessage;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
&rootJSON = CreateJsonObject();
/* Fake a 404 Error */
&ResponseStatusCode = 404;
&errorMessage = "The resource you requested does not exist.";
/* force an error - This will jump to the OnEror Method */
throw CreateException(99999, &ResponseStatusCode, &errorMessage);
/* ------- */
/* No code below here will run because of the throw above */
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Local Exception &exception = &msRequest.IBException;
%This.OnErrorHttpResponseCode = &exception.MessageNumber;
Local JsonObject &rootJSONError = CreateJsonObject();
&rootJSONError.AddProperty("error", &exception.ToString( False));
Return &rootJSONError.ToString()
end-method;
The response is what we expected. This makes sense that it would work because we are setting response properties in the onError
method and we are using data that is “given” by the exception object.
You will notice that there is some additional information contained in the error message that has the context of where the error was thrown. This would make no sense to the client and should not be included. This was supposed to be removed by passing false
to this statement &exception.ToString( False)
according to PeopleBooks. However, that seems like another bug. Death by a thousand cuts! ๐
|
|
This is not ideal but I could see where you build up your onError
method to have some logic on what status codes to return based on the &exception.MessageNumber
. Additionally, if you wanted more control over the output message you may need to inspect the exception
object and re-run it through your own message catalog retrieval. We will see a rough example of this below.
First let’s create a message catalog to represent our 404 error.
We are going to make some major changes to our handler.
Let’s look at what we are changing:
onError
, we pull out the passed in exception object.import PS_PT:Integration:IRequestHandler;
class statusCodeExampe1 implements PS_PT:Integration:IRequestHandler
method onRequest(&msRequest As Message) Returns Message;
method onError(&msRequest As Message) Returns string;
property integer OnErrorHttpResponseCode;
property string OnErrorContentType;
property JsonObject rootJSON;
private
method extractCleanerExceptionMessage(&inException As Exception) Returns string;
end-class;
method onRequest
/+ &msRequest as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &response;
&response = CreateMessage(@("Operation." | &msRequest.OperationName), %IntBroker_Response);
&rootJSON = CreateJsonObject();
/* force an error - This will jump to the OnEror Method */
throw CreateException(32100, 1, "", "some-key-value");
/* ------- */
/* No code below here will run because of the throw above */
&rootJSON.AddProperty("guid", GetJavaClass("java.util.UUID").randomUUID().toString());
If &response.SetContentString(&rootJSON.ToString()) Then
End-If;
Return &response;
end-method;
method onError
/+ &msRequest as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Local Exception &exception = &msRequest.IBException;
Local string &messageSetConcat;
&messageSetConcat = &exception.MessageSetNumber | "-" | &exception.MessageNumber;
Evaluate &messageSetConcat
When = "32100-1"
%This.OnErrorHttpResponseCode = 404;
Break;
When-Other
/* DO NOTHING - TAKE DEFAULT */
Break;
End-Evaluate;
Local string &errorMessage = %This.extractCleanerExceptionMessage(&exception);
Local JsonObject &rootJSONError = CreateJsonObject();
&rootJSONError.AddProperty("error", &errorMessage);
Return &rootJSONError.ToString()
end-method;
method extractCleanerExceptionMessage
/+ &inException as Exception +/
/+ Returns String +/
/* Re-run the MsgGetTex on the exception object so we have better control over the output */
Local string &return;
Evaluate &inException.SubstitutionCount
When = 0
&return = MsgGetText(&inException.MessageSetNumber, &inException.MessageNumber, "");
Break;
When = 1
&return = MsgGetText(&inException.MessageSetNumber, &inException.MessageNumber, "", &inException.GetSubstitution(1));
Break;
When = 2
&return = MsgGetText(&inException.MessageSetNumber, &inException.MessageNumber, "", &inException.GetSubstitution(1), &inException.GetSubstitution(1));
Break;
When = 3
&return = MsgGetText(&inException.MessageSetNumber, &inException.MessageNumber, "", &inException.GetSubstitution(1), &inException.GetSubstitution(1));
Break;
When-Other
&return = &inException.ToString( False);
Break;
End-Evaluate;
Return &return;
end-method;
The response with these changes has our 404 status code. Additionally, the error message in the body is much cleaner. It should not really be this hard but that is the cards we have been dealt with the framework.
|
|