Spring Integration - Service Activator - Method Signature - spring-integration

I have a general question. We are upgrading some old code to v4.1.3 of spring-integration. Let's say we have a service activator that receives a domain object of type Foo, and returns the same object on the output channel (after changing some properties of that object).
Our existing code has signatures like below. Is it the right convention? If I don't need the headers, can I return my payload directly and will the framework wrap it into a Message?:
public Message<Foo> computeValue(Foo payload, #Headers Map<String, Object> headerMap) {
//...
return MessageBuilder.withPayload(payload).copyHeaders(headerMap).build();
}

Yes, you don't need do that. More over that is pointless because in case of Service Activator the Framework populates request headers to the reply message independently of your effort.
So, consider do not care about headers at all if you don't need to do some specific logic on the matter.

Related

ServiceStack: Generate OpenAPI spec without creating the Service implementation classes

ServiceStack has support for OpenAPI and can generate an OpenAPI spec. However, for APIs/endpoints to be generated in the spec, it is not enough to specify the API details using the Route attributes as described here, you also need to create the Service classes that (eventually) implement the functionality.
Is there a way to make the OpenAPI specification include everything without having to create the Service classes that go with them?
The reason is that sometimes you just want to work on the specification, not implementation (even though you can just skip implementation details and throw a NotImplementedException), and creating those Service classes just to get the spec to show is annoying.
If it doesn't have an implementation it's not a Service and therefore wont have any of ServiceStack's metadata or features available for it.
If you want to skip their implementation you can just create stub implementations for them, e.g:
public class MyServices : Service
{
public object Any(MyRequest1 request) => null;
public object Any(MyRequest2 request) => null;
public object Any(MyRequest3 request) => null;
}

DDD / CQRS - Does a request handler (or controller) can throw exceptions defined at the domain level?

Good morning,
Let's say, we've a domain defining an exception such as ObjectNotFoundException which expect an identifier (VO), defined at the domain model.
Question
Can we throw domain exceptions from the request handlers directly, for instance:
class ObjectRequestHandler implements RequestHandler
{
...
public function __invoke(Request $request, Response $response)
{
// Will self-validate and throw an exception if not a valid UUID
$objectId = ObjectId::fromString(strval($request->param('object_id'])));
$object = $this->repository->find((string)$objectId);
if (NULL === $object) {
// Exception defined at the domain level...
throw new ObjectNotFoundException($objectId);
}
...
}
}
Doing this also lead to usage of the identifier VO in the request handler... It MUST be also noted that the throwed exception will be catched by the default exception handler which in turn, will prepare and send a JSON response.
Finally, note that the request handler here, is an implementation detail, not part of the question. Please don't comment about it.
Thank you.
Your example shows the correct usage of the repository to fetch an object from the data store based on an identifier.
Let's unpack and expand the workflow a little more to fit the paradigms of DDD, to help answer the question:
API Controller (or Request Handler) would invoke an Application Service with request params sent by the callee.
Request params forwarded to the Application Service can be simple data (like JSON) or can be objects (like DTOs)
Application Service has access to the correct repository associated with the object.
Repositories are outside the domain layer
Application Service would load the objects into memory using these repositories before handing over the control to (or invoking a method in) the domain layer.
The ObjectNotFound error is thrown typically from the repository if no object is found for the given identifier
The domain layer typically receives all objects it needs to work on from the Application Service or builds objects using factory methods.
The actual process is all about assigning or transforming attribute values according to business rules while ensuring invariant rules are satisfied. So the kind of errors that Domain Layer throws is Business Rule Errors (or Validation Errors).
So,
ObjectNotFoundException is not a Domain Exception
You are not at the domain level yet, so calling the identifier as a ValueObject is incorrect
Ignoring Application Services for a moment, you are spot on in your usage of the concept. The code example is correct in structure. It's just the terms that need to be clarified.

Representing thread pooling in Spring Integration rather than ExecutorService

Currently, code similar to the following exists in one of our applications:
#Component
public class ProcessRequestImpl {
private ExecutorService executorService;
public processRequest(...) {
// code to pre-process request
executorService.execute(new Runnable() {
public void run() {
ProcessRequestImpl.this.doWork(...);
}
}
}
private void doWork(...) {
// register in external file that request is being processed
// call external service to handle request
}
}
The intent of this is to create a queue of requests to the external service. The external service may take some time to process each incoming request. After it handles each one, it will update the external file to register that the specific request has been processed.
ProcessRequestImpl itself is stateless, in that all state is set in the constructor and there is no external access to that state. The process() method is called by another component in the application.
If this were to be implemented in a Spring Integration application, which of the following two approaches would be best recommended:
Keep the above code as is.
Extract doWork(), into a separate endpoint, configure that endpoint to receive messages on a channel, and to use configuration to achieve the multi threading in place of the executor service.
Some of the reasons we are looking at Spring Integration are as follows:
To remove the workflow logic from the code itself, so that the workflow and the chain of processing is evident on a higher level.
To simplify each class, enhancing readability and testability.
To avoid threading code if possible, and define that at a higher level of abstraction in configuration.
Given the sample code, could those goals be achieved using Spring Integration. Also, what would be an example of the DSL to achieve that.
Thanks
Something like
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(SomeGatewayInterface.class)
.handle("someBean", "preProcess")
.channel(MessageChannels.executor(someTaskExecutorBean())
.handle("someBean", "doWork")
.get();
The argument passed to the gateway method become the payload of the preprocess method, which would return some object that becomes the message payload, which becomes the parameter passed to doWork.

Global request/response interceptor

What would be the easiest way to setup a request/response interceptor in ServiceStack that would execute for a particular service?
A request filter (IHasRequestFilter) works fine but a response filter (IHasResponseFilter) is not triggered if the service returns non 2xx status code. I need to retrieve the status code returned by the method as well as the response DTO (if any).
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application and I couldn't find a way clean way to isolate per functionality the tasks that need to be executed in those methods.
Is there some extension point in ServiceStack that I am missing that would allow me to execute some code before each service method and after each service method? A plugin would be ideal but how can I subscribe to some fictitious BeforeExecute and AfterExecute methods that would allow me to run some custom code?
UPDATE:
Just after posting the question I found out that global response filters are executed no matter what status code is returned by the service which is exactly what I needed. So one last question: Is it possible to retrieve the service type that will handle the request in a request filter? I need to check whether this service is decorated by some custom marker attribute.
I have found out a solution to my question about how to retrieve the service type in a custom request/response filter:
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var metadata = EndpointHost.Metadata;
Type serviceType = metadata.GetServiceTypeByRequest(requestDto.GetType());
...
}
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application
Quick note, you can opt-in and choose only what requests should use a custom service runner, e.g:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return useCustomRunner(actionContext.RequestType)
? new MyServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}
IHttpRequest has OperationName. I think thats what you are after.

ServiceStack Request DTO with variable number of properties

I'd like to create an endpoint that is the front end for a query service and I'd like to support a scenario where any number of arguments can be passed into the service via querystring parameters.
This is the sort of URL I want:
/queries/MyQuery?argument1=value&arg2=value
The DTO object structure itself is fairly straightforward (a property such as Dictionary<string, object>) but I'm stuck on what the route should look like. Is this possible via the RouteAttribute or do I need to go another direction?
Here's a good answer that explains Routing in ServiceStack.
Only the PathInfo is apart of the Route, the Request DTOs on all routes/services are also automatically populated based on the Request Params on the QueryString/FormData etc.
So if you know what the QueryString is going to be you can just add it as properties on the Request DTO and they will get automatically populated.
If you don't know what they are, but you still want access to the QueryString you can get it from the base.Request property in your Service, e.g:
class MyServices : Service
{
public object Get(MyQuery request)
{
foreach (var entry in base.Request.QueryString) {
...
}
}
}

Resources