can somebody please clarify which type of message communication patterns:
Point-To-Point
Request-Reply
Publish/Subscribe
... is used in GENERATED Vert.X Service Proxy classes for RESTful CRUD app (which has 4 HttpServerVerticles which communicates with DatabaseVerticle and those are deployed by MainVerticle)?
Thank you in advance.
I persume it's Request-Reply since it sends Http Request and recieves Http Response since in "Vert.x in action" it states (in Chapter 3.1.4):
If you need message consumers to get back to the entity that sent the event then go for request-reply.
Any help/advice is greatly appreciated.
TL;DR: Request-Reply
If you look in the docs for service proxy (https://vertx.io/docs/vertx-service-proxy/java/) you can see in the beginning that it saves you from doing the following "boiler-plate" code:
JsonObject message = new JsonObject();
message.put("collection", "mycollection")
.put("document", new JsonObject().put("name", "tim"));
DeliveryOptions options = new DeliveryOptions().addHeader("action", "save");
vertx.eventBus().request("database-service-address", message, options, res2 -> {
if (res2.succeeded()) {
// done
} else {
// failure
}
});
Also from the same link:
A service is described with a Java interface containing methods
following the async pattern. Under the hood, messages are sent on the event bus to invoke the service and get the response back. But for
ease of use, it generates a proxy that you can invoke directly (using
the API from the service interface).
Related
I have got two Spring Boot application. First one is REST application. The REST one is communicating with second application through RabbitMQ message queue. I'm sending a request to method with the #GetMapping("/") and this method producing a message to example-queue. A method with #RabbitListener(queues = {"example-queue"}) taking the message and create a object at database. Now, how can I send my response (saved object) to the method with #GetMapping("/")? I need a response from consumer to ResponseEntity.ok();. How can I do that? Thank you.
Just see if you can make the interaction with RabbitMQ consumer as a request-reply pattern.
The #RabbitListener can just return your object and be marked with a #SendTo. This way the framework will look into a replyTo property of the request message.
On the producer side you can just use an AmqpTemplate.convertSendAndReceive().
See more in docs: https://docs.spring.io/spring-amqp/docs/current/reference/html/#request-reply
I am learning spring integration reading/watching a different stuff but I can't understand what service activator is.
I understood that there are two types of integration:
chanel and gateways. chanel is unidirectional integration but gateways is request/reply model. Gateways can be inbound(our system gets request and sends response) and outbound (our system sends request and receives response)
When I read about gateways I often see termin "service activator"
Could you clarify what does it mean ?
The outbound gateway is essentially a particular case for a service activator abstraction for request/reply scenarios. Another case is an outbound channel adapter, which is a one-way, but still can be treated as a service activator because when we send a message to its inputChannel, we are going to call some code - which we can treat as a service. Therefore activating it.
A general component service activator exists there for all the use-cases which are not covered by particular implementation. Let's imaging you need to call some REST service. Right, you can use an HTTP Outbound Gateway with some specific options. Or you can write some custom code which uses a RestTemplate to call that service. you wrap your code into a service activator configuration and you end up with the same behavior for the whole integration solution.
A service activator is a call to a method in a bean.
<service-activator ref="myService" method="aMethod"/>
will call
#Service
public class MyService {
public A aMethod(#Header(value = "param1") String param){
//code
}
}
#Header annotation allows to use an existing value in the header. That is an example.
You can also use it like this:
<service-activator expression="#myService.aMethod('My param')"/>
I have a requirement were some of the STOMP websocket connections needs to be handled synchronously.
Meaning I have a client (spring) subscribed to a topic ("/topic").
I have a server (spring) that has defined the broker ("/topic") also defined handlers ("/app/hello").
Now is it possible for the client to send a request to /app/hello and then wait for a response before sending the next request to /app/hello.
How do I return value on my sever (STOMP spec says about RECEIPT frames but I don't think this is something that can be manually controlled).
How do I wait for the value on my client after a send.
To connect a Java client to a websocket endpoint you can use the tyrus reference implementation of JSR356 - Websockets For Java.
Basically you will need to implement a client endpoint (javax.websocket.Endpoint) and a message handler (javax.websocket.MessageHandler). In the endpoint you register the message handler with the current session on open:
public class ClientEndpoint extends Endpoint {
...
#Override
public void onOpen(final Session aSession, final EndpointConfig aConfig) {
aSession.addMessageHandler(yourMessageHandler);
}
}
To connect to the server endpoint you can use the ClientManager:
final ClientManager clientManager = ClientManager.createClient();
clientManager.connectToServer(clientEndpoint, config, uriToServerEndpoint);
The message handler's onMessage method will be invoked, if the server endpoint sends something to the topic.
Depending on your needs you can either choose to implement the mentioned interfaces or use the corresponding annotations.
UPDATE:
The STOMP website lists several implementations of the STOMP protocol. For Java there are Gozirra and Stampy. I have no experience with these frameworks but the examples are pretty straight forward.
I am developing a jax-ws webservice that pushes messages asynchronously to the subscribed consumers using one-way operation.
Unfortunatelly with each notification, server awaits a HTTP202 response confirmation which blocks the thread for a fraction of a second. This is affecting the performance of the system and I am looking for a way around this.
Is there any way to execute a web-service one-way call and ignore the HTTP response status?
Ok, so after spending a lot of time on this I have found two solutions:
1) Using Apache HTTPComponents, which provide AsyncHTTPClient with nice API allowing us to build a HTTP response from the scratch.
2) More web-service oriented solution based on Apache CXF platform (which includes the HTTPClient implementation) - first we need to set the global Bus property:
Bus bus = BusFactory.getDefaultBus();
bus.setProperty(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE);
Then, we use custom interceptor to set the message exchange property to asynchronous:
final class SkipWaitInterceptor extends AbstractSoapInterceptor {
SkipWaitInterceptor() {
super(Phase.SETUP);
}
#Override
public void handleMessage(final SoapMessage message) throws Fault {
message.getExchange().setSynchronous(false);
}
}
Finally, we register the interceptor on our asynchronous Endpoint
org.apache.cxf.endpoint.Client client =
org.apache.cxf.frontend.ClientProxy.getClient(this.notificationConsumer);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
cxfEndpoint.getOutInterceptors().add(new SkipWaitInterceptor());
That's all, one-way operation responses no longer block the communication.
I am using CometD and I have a service setup (Java on the server side) as follows:
http://localhost:8086/service/myService/get-player-details?params={id:1234}
This works fine in practice but what concerns me is that any user can query my service using the above URL and retrieve another players details.
What would be the suggested way of guarding against such an issue? Would authorizers be the correct approach?
If the URL you posted is a mapped to CometD, then I strongly discourage you to use those kind of URLs to pass information such as params in the URL.
First, this will not work if you use other transports that are not HTTP, such as WebSocket.
Second, as you note that URL may expose information that you don't want to expose.
I recommend that you change the way you retrieve information from the server to not use URLs but only messages.
If all your communication with the server happens via messages, CometD on the server already validates that the message comes from a client that was allowed to handshake. You just need to enforce the right authentication checks at handshake time using a SecurityPolicy as explained the in authentication section.
The messages will have this form, using the CometD JavaScript client library:
cometd.publish("/service/player", { action:"get", playerId: 1234 });
There may be variations of this pattern where you want to put the "action" into the channel itself, for example:
cometd.publish("/service/player/get", { playerId: 1234 });
In this way, you have more little services (each responding to a different channel and therefore to a different action), which may be desirable.
Reading the examples of the services section may give you additional information.
I don't recommend to put the playerId into the channel for two reasons:
to avoid to create too many channels
to have this information promptly available in the code, so you don't need to parse the channel (although CometD support use of parameters in channels); parsing is more costly than just doing message.get("playerId").
To send the response to the client, the server can just call:
#Service
public class GetPlayer
{
#Session
private LocalSession sender;
#Listener("/service/player/get")
public void perform(ServerSession session, ServerMessage message)
{
Map<String, Object> player = retrievePlayerInfo(message.get("playerId"));
session.deliver(sender, message.getChannel(), player);
}
}
Note usage of ServerSession.deliver() to return the response to that specific client.
What above guarantees you (with a proper SecurityPolicy) that only authenticated clients can send and receive messages.
What you need to do now is to put in place the right authorizations, in particular that player 123 cannot play as player 789 by hacking the CometD messages that it sends.
This is the job for Authorizers, see the section and the examples in the Authorizers documentation.
What you must do is to establish a relation between the user that authenticated with the playerIds that she's allowed to see. That is application specific and it's the core of your Authorizer implementation.
With proper SecurityPolicy and Authorizers in place, your application is safe from the concerns of your question.
Strictly speaking, Authorizers may be enough, but typically if you want an authorization policy to be enforced, you also need authentication, which is provided by the SecurityPolicy.