Dynamic REST endpoint creation with Spring Boot - java

I'm working on a framework that has a Spring Boot Java layer and a C++ layer that contains the core logic. The C++ layer is modular such that many services with unique responsibilities and commands share common components, including a command processor. The command processor communicates with the Java layer (which is also the same for all services) via Thrift RPC.
Currently, users execute commands through a single executeCommand REST endpoint at the Java level by specifying a command name and set of parameters.
POST http://localhost:8388/framework/executeCommand
JSON Body {"commandName": "aCommand", "parameters": {"param1": "value1", "param2": "value2"}}
Is there a way to dynamically generate REST endpoints based on the set of commands provided by the C++ layer? Ex... each command would have an endpoint such as
POST http://localhost:8388/framework/aCommand
JSON Body {"parameters": {"param1": "value1", "param2": "value2"}}
OR
GET http://localhost:8388/framework/aCommand?param1=value1
Ex... at startup, the Java layer would query the C++ layer for the set of commands and other relevant information such as the appropriate REST method. With this information the Java layer would generate an endpoint for each command.
Thanks!

You could use a path variable in your REST controller to accept different command types, something like so:
#RestController
#RequestMapping("/command")
#RequiredArgsConstructor
class CommandController {
private final CommandService commandService;
#PutMapping("/{commandType}")
public CommandResult handleCommand(#PathVariable("commandType") String commandType,
#RequestParam Map<String, String> params) {
return commandService.execute(commandType, params);
}
}
(Here CommandService is a service that loads available commands at startup and then validates and executes a requested command).
You could then run a command with a request like PUT http://localhost:8080/command/someCommand?param1=value1&param2=value2
UPDATE
Some solutions for the clarified requirements (dynamic REST controller creation):
https://github.com/tsarenkotxt/poc-spring-boot-dynamic-controller
Make #RestController at runtime
Spring boot runtime add controller?

Related

Grails 2.4.5 Rest API GET Request: Can't get Response Body from CUrl and from React UI, but can get it from Postman and Browser

Grails 2.4.5 REST Controller returning List of non Domain object DTO
What's the best way to turn a method/action into a REST Resource accessible through a GET request, without returning a domain class/entity, but with a non-domain/entity DTO class?
With SpringBoot, it will look like this:
#RestController
class EmployeeController { ...}
/**
**I am not sure that even in Spring/SpringBoot you can return a list of non entity class DTO.
** Can you return a random non entity
**/
#GetMapping("/employees")
List<EmployeeDTO> all() {
return repository.findAll();
}
For my Grails project, I am trying to return a list of DTO object having data from different domain/entities. Since the class is not a Grails domain class, how do you do that, since it doesn't follow the Grails convention?
I have the code as below:
class ClassNameController extends RestfulController{
/**
** Grails usually wants you to use call the parent constructor and and put a domain class as
** a parameter like super (DomainClass).
** In my case, since I have a non-conventional Controller which combines different data
** sources/domains/entities, how do I implement my method/action to turn it into a Grails REST
** Resource?
** Is there an annotation like #RestController, #ResponseBody and #GetMapping in Grails or can they be used in Grails too, since Grails 2.4.5 is built on top of Spring?
**/
/**
** I used just one of the multiple domain/entity classes as a parameter to the parent constructor,
** in order to follow that convention like this below.
**/
ClassNameController(){
super(OneDomainClassOutOfTheManyDomainClassesInsideDTOClass)
}
List<ClassDTO> getAllDTOs(){
//allClassDTOs() is a private method inside same controller returning a list of all classDTOs
List<ClassDTO> classDTOsList = allClassDTOs()
respond classDTOsList, status: 200
}
With that code, I can see the data displayed in Postman as well as inside the browser. However, I am not able to see the data when testing with CUrl, somehow looking at the log, Grails considers the request as successful and redirect to the home page. I am not sure why that's the case. I even removed any security to see if it was due to the Oauth Access token, but I can see that it's not the case, as even with #Secured(['IS_AUTHENTICATED_FULLY']), I can see in the logs of Spring Security that the user has been authenticated successfully and the authorization access has been granted successfully.
Pretty much, I am looking for a sample example of a simple Grails REST API that doesn't use the Grails convention and returns a non domain object.

Calling standard contact Seibel Business Service from Java application

I want to call the standard "Contact" Seibel Business Service from my java program. I will appreciate if you can point me to some resources on the same.
Thanks.
There are bunch of documentation and samples online.
You need to replace the Echo service by the Contact service.
I post just an example from Oracle website below:
Aside from the business object and business component API, the primary
point of integration with the Siebel application is by using business
services. There are several ways to invoke a business service. The
simplest way is using the Siebel Java Data Bean directly, as shown in
the following example.
Alternatively, Siebel Tools provides a Code
Generator which creates, for any business service, Java classes that
invoke the business service. The generated code may invoke the
business service either using the Siebel Java Data Bean or using the
Siebel Resource Adapter. The creation and use of generated code is
described in the next section. The Siebel Resource Adapter is part of
the Java EE Connector Architecture, which is described in About the
Siebel Resource Adapter. The following is an example of invoking a
business service directly using the Siebel Java Data Bean.
import com.siebel.data.SiebelException;
import com.siebel.data.SiebelPropertySet;
import com.siebel.data.SiebelService;
public class BasicDataBeanTest {
public static void main(String[] args) throws SiebelException {
SiebelDataBean dataBean = new SiebelDataBean();
dataBean.login("siebel://mymachine:2321/siebel/SCCObjMgr_enu", "USER", "PWD", "enu");
SiebelService businessService = dataBean.getService("Workflow Utilities");
SiebelPropertySet input = new SiebelPropertySet();
SiebelPropertySet output = new SiebelPropertySet();
input.setValue("Please echo this");
businessService.invokeMethod("Echo", input, output);
System.out.println("Output: " + output.toString());
}
}

Spring: How to export objects methods via non-HTTP protocol

I have a collection of stateless scala/Java APIs, which might look like:
class UserService {
def get(id: UserIDType): User { ... }
def update( user:User): User { ... }
...
}
where User has a set of inspectable bean properties. I'd like to make these same APIs not only available over HTTP (which I know how to do), but also other, more performant non-HTTP protocols (ideally also running in the same process as the HTTP server). And more importantly, automate as much as possible including generation of client APIs that match the original Java API, and the dispatching of method calls following network requests.
I've found Spring's guide on remoting
However, this looks limited to HTTP (text not binary). What I'd really love is a library/other method that:
lets me scan for registered/annotated services and describes methods and parameters as data
lets me easily dispatch method calls (so that I'm in control of the sockets, communication protocols and whatnot and can chose a more performant one than HTTP).
i.e. the kinds of things that Spring's DispatcherServlet does internally, but without the HTTP limitations.
Ideas?
Background
I'd like to make a set of stateless service API calls available as network services with the following goals:
Some of the APIs should be available as REST calls from web pages/mobile clients
A superset of these APIs should be available internally within our company (e.g. from C++ libraries, python libraries) in a way that is as high-performance (read low-latency) as possible, particularly when the service and client are:
co-located in the same process, or
co-located on the same machine.
automate wrapper code for the client and server. If I add a method a service API, or and an attribute to a class, no-one should have to write additional code in client or server. (e.g. I hit a button and a new client API that matches the original Java/scala service is auto-generated).
(1) is easily achievable with Spring MVC. Without duplication of classes I can simply markup the service: (i.e. service is also a controller)
#Controller
#Service
#RequestMapping(...)
class UserService {
#RequestMapping(...)
def get(#PathVariable("id") id: UserIDType): User { ... }
#RequestMapping(...)
def update( #RequestBody user:User): User { ... }
...
}
With tools like Swagger (3) is easily achievable (I can trivially read the Swagger-generated JSON spec and can auto-generate C++ or Python code that mimics the original service class, it's methods, parameter names and the POJO parameter types).
However, HTTP is not particularly performant, so I'd like to use a different (binary) protocol here. Trivially, I can use the this same spec to generate a thrift .idl or even directly generate client code to talk Thrift/ProtocolBuffers (or any other binary protocol) while also providing to the client an API that looks just like the original Java/scala one.
Really -- the only tricky part is getting a description of the service method and then actually dispatching a method calls. So -- are there libraries to help me do that?
Notes:
I'm aware that mixing service and controller annotations disgusts some Spring MVC purists. However, my goal really is to have a logical API, and automate all of the service embodiments of it (i.e. the controller part is redundant boilerplate that should be auto-generated). I'd REALLY rather not spend my life writing boilerplate code.

How to aggregate JAX-RS responses from multiple services

We have a user dashboard which is displayed after login. The dashboard is composed of multiple widgets.
Each widget pulls content from separate restful service.
for eg : /news /mails /questions /alerts .
Each widget calls the service after it is loaded on the page. This way there are multiple webservice calls.
Is there a way to reduce multiple calls.
The way it should work is when the page is loaded first time the service should return aggregated data for all the widgets in single call.
Each service should also be available independently so that it can be used for refreshing a single widget, and for other system integration.
Note :A widget is this case is any javascript portlet which can consume json data from restful service.
All services are within a single web-application.
How can we aggregate the responses from multiple services and combine into a single JSON?
If you can add your own JAX-RS service simply add a new service that calls each of the others and creates the aggregated response.
for instance:
GET http://myservice.com/rest/aggregate?service=news&service=mails&service=questions
The url prefix for the serivce could be supplied as a separate encoded parameter, or provided within the aggregation service.
If all of these run within the same server just use the existing API for the other services to create the aggregated response instead.
Remember that json services are just methods, so to elaborate on #Vengard's answer (please accept that one as it was earlier) you cou(ld create a aggregate method which would look something like this:
#Path ("15218462")
class Test {
#Path ("aggregate")
public Map<String, Object> aggregate(#QueryParam("service") List<String> services) {
Map<String, Object> result = new HashMap<>();
for (String serviceName : services) {
if(serviceName.equals("mails") {
result.put("mails", mails());
}
// ... etc
}
}
#Path
public List<String> mails() {
// .... processing code ...
}
}
If the services are not under your control and you don't mind being dependent on 3rd parties you might want to check out something like Yahoo pipes (http://pipes.yahoo.com/pipes/)

Is there any framework for performing RPC from javascript to Java bean(spring bean)?

This is the short description of my situation...
I have spring bean BookingServiceImpl which implements BookingService
BookingService has method: RoomDescription getRoomDescriptionById(String roomId);
I also have JSP page with javascript on it
I want to do something like this in javascript
var roomDescription = bookingService.getRoomDescriptionById(222);
/// ... use roomDescription
The question is: is there any existent framework which does things like that (magically allows to cal spring beans from javascript without additional boiler-plate code, assuming all parameters and method results are JSON-friendly)?
Spring provides mechanisms to expose RESTful endpoints via the Web MVC framework
The documentation is very good. A Controller definition for your specific example could look like this:
#Controller
#RequestMapping(value = "/rooms/{roomId}", method = RequestMethod.GET, produces="application/json")
#ResponseBody
public Room getRoom(#PathVariable String roomId, ModelMap modelMap) {
return bookingService.getRoomById(roomId);
}
On the javascript side, you could use jQuery to make an ajax call to retrieve the data. Here is an example of what that could look like:
$.getJSON('http://yourserver.com/rooms/222',
function(room) {
// Do something with room.description
});
This is a basic example (without proper error handling, security, etc). It's the closest thing to an existent framework that I'm aware of for Spring RESTful calls from javascript. If you need to access the Room data on the client side javascript then you'll need to expose it via some Spring construct (e.g. a Controller)
Take a look at DWR. This is as close as you will get to creating js clients.
http://directwebremoting.org/dwr/documentation/server/integration/spring.html

Categories