org.pipservices3.rpc.services.CommandableHttpService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pip-services3-rpc Show documentation
Show all versions of pip-services3-rpc Show documentation
Networking and communication platform for Pip.Services in Java
The newest version!
package org.pipservices3.rpc.services;
import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.Response;
import org.glassfish.jersey.process.Inflector;
import org.pipservices3.commons.commands.CommandSet;
import org.pipservices3.commons.commands.ICommand;
import org.pipservices3.commons.commands.ICommandable;
import org.pipservices3.commons.config.ConfigParams;
import org.pipservices3.commons.errors.ConfigException;
import org.pipservices3.commons.refer.IReferences;
import org.pipservices3.commons.refer.ReferenceException;
import org.pipservices3.commons.run.Parameters;
/**
* Abstract service that receives remove calls via HTTP/REST protocol
* to operations automatically generated for commands defined in ICommandable components.
* Each command is exposed as POST operation that receives all parameters in body object.
*
* Commandable services require only 3 lines of code to implement a robust external
* HTTP-based remote interface.
*
* ### Configuration parameters ###
*
* - base_route: base route for remote URI
*
- dependencies:
*
* - endpoint: override for HTTP Endpoint dependency
*
- controller: override for Controller dependency
*
* - connection(s):
*
* - discovery_key: (optional) a key to retrieve the connection from IDiscovery
*
- protocol: connection protocol: http or https
*
- host: host name or IP address
*
- port: port number
*
- uri: resource URI or connection string with all parameters in it
*
*
*
* ### References ###
*
* - *:logger:*:*:1.0 (optional) ILogger components to pass log messages
*
- *:counters:*:*:1.0 (optional) ICounters components to pass collected measurements
*
- *:discovery:*:*:1.0 (optional) IDiscovery services to resolve connection
*
- *:endpoint:http:*:1.0 (optional) {@link HttpEndpoint} reference
*
*
* ### Example ###
*
* {@code
* class MyCommandableHttpService extends CommandableHttpService {
* public MyCommandableHttpService() {
* super();
* this._dependencyResolver.put(
* "controller",
* new Descriptor("mygroup","controller","*","*","1.0")
* );
* }
* }
*
* MyCommandableHttpService service = new MyCommandableHttpService();
* service.configure(ConfigParams.fromTuples(
* "connection.protocol", "http",
* "connection.host", "localhost",
* "connection.port", 8080
* ));
* service.setReferences(References.fromTuples(
* new Descriptor("mygroup","controller","default","default","1.0"), controller
* ));
*
* service.open("123");
* System.out.println("The REST service is running on port 8080");
* }
*
*
* @see RestService
*/
public class CommandableHttpService extends RestService {
private ICommandable _controller;
protected CommandSet _commandSet;
protected boolean _swaggerAuto = true;
/**
* Creates a new instance of the service.
*
* @param baseRoute a service base route.
*/
public CommandableHttpService(String baseRoute) {
this._baseRoute = baseRoute;
_dependencyResolver.put("controller", "none");
}
/**
* Sets references to dependent components.
*
* @param references references to locate the component dependencies.
* @throws ReferenceException when no found references.
* @throws ConfigException when configuration is wrong.
*/
@Override
public void setReferences(IReferences references) throws ReferenceException, ConfigException {
super.setReferences(references);
_controller = (ICommandable) _dependencyResolver.getOneRequired("controller");
}
/**
* Configures component by passing configuration parameters.
*
* @param config configuration parameters to be set.
*/
public void configure(ConfigParams config) throws ConfigException {
super.configure(config);
this._swaggerAuto = config.getAsBooleanWithDefault("swagger.auto", this._swaggerAuto);
}
/**
* Registers all service routes in HTTP endpoint.
*/
@Override
public void register() {
if (_controller == null)
return;
_commandSet = _controller.getCommandSet();
var commands = _commandSet.getCommands();
for (ICommand command : commands) {
registerRoute(HttpMethod.POST, command.getName(), new Inflector() {
@Override
public Response apply(ContainerRequestContext request) {
return executeCommand(command, request);
}
});
}
if (this._swaggerAuto) {
var swaggerConfig = this._config.getSection("swagger");
var doc = new CommandableSwaggerDocument(this._baseRoute, swaggerConfig, commands);
this.registerOpenApiSpec(doc.toString());
}
}
private Response executeCommand(ICommand command, ContainerRequestContext request) {
var correlationId = this.getCorrelationId(request);
InstrumentTiming timing = instrument(correlationId, _baseRoute + '.' + command.getName());
try {
String json = getBodyAsString(request);
Parameters parameters = json == null ? new Parameters() : Parameters.fromJson(json);
Object result = command.execute(correlationId, parameters);
return sendResult(result);
} catch (Exception ex) {
timing.endFailure(ex);
return sendError(ex);
} finally {
timing.endTiming();
}
}
}