Foren

Service Builder and 3rd party application

Alexander Volk, geändert vor 7 Jahren.

Service Builder and 3rd party application

New Member Beiträge: 2 Beitrittsdatum: 08.06.16 Neueste Beiträge
Hi!

We faced with some problems in our application that uses Liferay 6.2 GA6.

The first one is - how to pass a JSONArray to remote service?. We found only one way to handle this:

public void doSmth(String list){
// convert string "list" to JSON
}

And this solution requires that requestBody should be in the next format:
{
  list: [
    {...},
    {...},
    ...
  ]
}

Ok, we can accept this in our inner dev. guide.
And now we want to integrate with the 3rd party application that periodically calls our API (Remote Services). And here is the problem: we can't specify format of request and this application always sends array as array and not as object with array inside.

How to solve it? Can I access requestBody in RemoteService?

The second problem is - remote servcie always returns "200 - OK" status code, even in server error case. And again in our app we can handle it, but for the 3rd party application this is the problem (if status code: 200 - do one thing, if 201 - another one, if 404 - another one and so on.).

How to return custom status code? Can I access response in RemoteService?

We found the next solution: https://web.liferay.com/web/vitor.silva/blog/-/blogs/using-restful-services-with-liferay.
Yes, it works. But implementation of this solution fully replaces RemoteService functionality, because it does the same things, and no need to have two API in one application. Our API is large and we can't replacy it partialy - for one method use: "portal_host/api/jsonws/bla-bla-service/method1" and for another: "portal_host/bla-bla-service/method2"

And if your advice will be use Spring Restful servlet - in this case I can't understand "what the pros of usage of RemoteServices?"
It allow quickly create API, but when you almost done it - you should return back and fully refactor it and waste more time?
thumbnail
David H Nebinger, geändert vor 6 Jahren.

RE: Service Builder and 3rd party application

Liferay Legend Beiträge: 14919 Beitrittsdatum: 02.09.06 Neueste Beiträge
Alexander Volk:
The first one is - how to pass a JSONArray to remote service?


This is a public method that you add to your XxxServiceImpl? Liferay will handle automatic JSON conversion from incoming JSON to the parameter types specified by your method. If you ask for a simple String, all you're going to get is a simple String. If you have an array or a List as a parameter, Liferay will marshal into the array or List for you.

And here is the problem: we can't specify format of request and this application always sends array as array and not as object with array inside.

How to solve it? Can I access requestBody in RemoteService?


That is a reflection of what you are using. If I define a method, public void process(String[] array), I'm going to get the array. But if I have an entity like:

@JSON
public class MyContainer {
    private String[] array;
}


and then define my method as public void process(MyContainer container), I should get the object with the embedded array.

How to return custom status code? Can I access response in RemoteService?


You throw an exception to get a non-200 return code, but you don't really have control over which one.

And if your advice will be use Spring Restful servlet - in this case I can't understand "what the pros of usage of RemoteServices?"
It allow quickly create API, but when you almost done it - you should return back and fully refactor it and waste more time?


Nah, I wouldn't say use spring rest servlets.

REST has it's place, but it depends mostly upon doing CRUD operations via the standard HTTP request types. They allow you to build the business logic in JS in the browser but still have a persistence layer via the REST calls.

A lot of times you'll see where REST is polluted to include scattered business logic in the REST handlers, but there's no established standard for where business logic belongs in RESTful implementations.

The Liferay remote services are a different animal. The methods are yours to create, you can include simple CRUD methods but most of us treat them like remote function calls, building in business logic, etc., into the remote service layer.

Why use the remote services? Automatic data marshaling, scaffolding support from Service Builder, injected access to XxxLocalService so the remote can access local data access, access to the PermissionChecker for easy permission checks, ...

So to me the Remote services and RESTful services have two completely different use cases.








Come meet me at the 2017 LSNA!
Alexander Volk, geändert vor 6 Jahren.

RE: Service Builder and 3rd party application

New Member Beiträge: 2 Beitrittsdatum: 08.06.16 Neueste Beiträge
David H Nebinger:
Alexander Volk:
The first one is - how to pass a JSONArray to remote service?


That is a reflection of what you are using. If I define a method, public void process(String[] array), I'm going to get the array. But if I have an entity like:

@JSON
public class MyContainer {
    private String[] array;
}


and then define my method as public void process(MyContainer container), I should get the object with the embedded array.

Come meet me at the 2017 LSNA!


I know that it can be made in this way. But in this case client app hase to send an array inside object in request body, an here is the problem: the client app is a 3rd party application and we cannot configure format of request. All that we can - just specify endpoint. So in request body we recieve jsonArray

[
  {"name": "anyName1", "description": "anyDescription1"},
  {"name": "anyName2", "description": "anyDescription2"}
]

and not jsonObject that includes jsonArray as you suggest.

{
  "array": [
    {"name": "anyName1", "description": "anyDescription1"},
    {"name": "anyName2", "description": "anyDescription2"}
  ]
}


According non-200 status:
if invoke any service without required parametes from http://localhost:8080/api/jsonws
you will get a response with status 200 and body like that:

{"exception":"java.lang.ClassCastException","message":"Conversion failed: ; <--- java.lang.NumberFormatException: For input string: \"\""}

How client can understand, that it was "Bad Request" - not all required parameters were set (or something else), and not 5xxx (internal server error)?

Again we have integration with some applications that send http request and all that we can do - just specify endpoint
thumbnail
Christoph Rabel, geändert vor 6 Jahren.

RE: Service Builder and 3rd party application

Liferay Legend Beiträge: 1554 Beitrittsdatum: 24.09.09 Neueste Beiträge
Alexander Volk:
Hi!
And now we want to integrate with the 3rd party application that periodically calls our API (Remote Services). And here is the problem: we can't specify format of request and this application always sends array as array and not as object with array inside.

How to solve it? Can I access requestBody in RemoteService?


Not sure if you can get that one to work at all. Servlets or maybe a portlets serveResource method seem to be the only solution in LR 6.2. We fiddled with that too for a while, but we could dictate the API. We also found, that the most convenient thing is to always just use strings and parse the JSON in our code.

Alexander Volk:

The second problem is - remote servcie always returns "200 - OK" status code, even in server error case. And again in our app we can handle it, but for the 3rd party application this is the problem (if status code: 200 - do one thing, if 201 - another one, if 404 - another one and so on.).

How to return custom status code? Can I access response in RemoteService?


No. The returncode 200 is hardcoded. The behavior was changed in EE Patch 119. After that patch Services return also 500 Server error and the error inside as content (maybe there are more returncodes than 500, but I only ever saw 500). I know that because Liferay forgot to update the javascript Liferay.Service() method. It isn't able to handle errors anymore and silently fails causing all kinds of issues in our applications.

Alexander Volk:

And if your advice will be use Spring Restful servlet - in this case I can't understand "what the pros of usage of RemoteServices?"
It allow quickly create API, but when you almost done it - you should return back and fully refactor it and waste more time?


Well, IMHO the trick to create remote JSON services with Service Builder was always just a workaround. We used it a lot since we could dictate the API. It was easier/faster/more convenient for us than creating servlets. But I am rather glad that Liferay 7 made our lives easier and such tricks are not required anymore.