Some example using SubProtocolWebSocketHandler and stompSubProtocolHandler? - spring

I can't find examples of use of stompSubProtocolHandler and SubProtocolWebSocketHandler?
I need extend this SubProtocolWebSocketHandler class?
private static class ProducerStompSessionHandler2 extends SubProtocolWebSocketHandler {
public ProducerStompSessionHandler2(MessageChannel clientInboundChannel,
SubscribableChannel clientOutboundChannel) {
super(clientInboundChannel, clientOutboundChannel);
// TODO Auto-generated constructor stub
}
}
I'm using a handler for a Sockjs java client that extend of StompSessionHandlerAdapter and is working. I can connect, subscribe and send messages:
private static class ProducerStompSessionHandler extends StompSessionHandlerAdapter {
...
}
But I see another user telling that there are two implementacions: SubProtocolWebSocketHandler and stompSubProtocolHandler.
https://stackoverflow.com/a/28306539/6243317
These are implementation of Java Websocket over STOMP clients? how use? advantages? why use this implementation?

To answer your main question in the title, I think this sample by Spring would be useful to you. The stompSubProtocolHandler is more server side in the sample, but I assume the logic will be the same for client.

Related

Spring MVC - How can I dynamically switch the implementing class?

My question is about finding the best technique for implementing a bean switcher for managing different sites with different persistent layers.
I designed a server for Customer management and e-eCommerce services.
For each service I am using an API layer, a Controller layer and a persistent layer.
This server is managing multiple sites for different clients.
Up until today, all my sites have used the same persistent layer for all the sites.
Recently, I have a new request for integrating the customers services from an outside server - In other words, Integration with external service.
I am trying to solve this by adding another persistent layer that uses the external service's API, and when I get request from this site, to switch the persistent layer to the outside service (Like a factory).
Lets assume I have details about the site which the request came from....
My goal is to use a kind of 'Factory' for switching between the persistent layers according to the parameters that I pull from the request.
How do I dynamically switch the implementing class of the interface using the Spring MVC tools?
I found this solution: https://www.baeldung.com/spring-dynamic-autowire, but I don't think it is the best solution.
Can anyone share a different technique to achieve my goal?
Thank you so much for any help!!!
Asaf
You can use Factory pattern to solve this issue.
You can define a class that will autowired all types of data services. You should first define an abstraction via interface something like this.
interface SomeDao {
...
}
#Service(name="someDaoMysql")
class SomeDaoMysqlImpl implements SomeDao {
...
}
#Service(name="someDaoApi")
class SomeDaoApiImpl implement SomeDao {
...
}
Once you have these different variants of the SomeDao interface, return one of them based on some parameters. A factory interface might look like this.
enum DaoType{
API,
MYSQL;
}
interface SomeDaoFactory {
SomeDao getDao( DaoType type);
}
#Component
class SomeDaoFactoryImpl implements SomeDaoFactory{
#Aurowired #Qualifier("someDaoMysql") SomeDao someDaoMysql;
#Aurowired #Qualifier("someDaoApi") SomeDao someDaoApi;
public SomeDao getDao( DaoType type){
switch(type){
case API:
return someDaoApi;
case MYSQL:
return someDaoMysql;
default:
throw new IllegalStateExecption("Unknown type"+type);
}
}
Usage
#Service
public class SomeFancyServiceImpl implements SomeFancyService{
#Autowired SomeDaoFactory someDaoFactory;
#Override
public void doSomething(){
SomeDao dao = someDaoFactory.getDao( API );
// do something with dao
}
}

#Gateway is not required if we use #MessagingGateway

From Spring 4.0 onwards #MessagingGateway was introdued. Using it if we have only one gateway method in our Gateway interface , then we don't need to annotate the Gateway method with #Gateway.
Below is my example, where both are working.
So, my question is can we stop using #Gateway when we have only one method in Gateway interface?
Code-1:
#MessagingGateway(name="demoGateway")
public interface DemoGateway {
#Gateway(requestChannel = "gatewayRequestChannel",replyChannel = "nullChannel")
void accept(Message<String> request);
}
Code-2:
#MessagingGateway(name="demoGateway",defaultRequestChannel =
"gatewayRequestChannel",defaultReplyChannel = "nullChannel")
public interface DemoGateway {
void accept(Message<String> request);
}
Yes. You are right. You can do approach 2 and leave the single method that confirms to the default configuration of #MessagingGateway without annotation.
However in practice, I will only move the truly default values to the MessagingGateway and leave other values to #Gateway annotation.
This is because it makes life and readability easier in the future if you have to add more methods to DemoGateway in the future.

How to have dynamic base URL with Quarkus MicroProfile Rest Client?

Quarkus using Rest Client, explains how to use the MicroProfile REST Client. For Base URL application.properties can be used.
org.acme.restclient.CountriesService/mp-rest/url=https://restcountries.eu/rest #
With above approach, cant have dynamic base URL.
Able to achieve it by using RestClientBuilder as explained in MicroProfile Rest Client. Downside of this approach is not having auto-negotiation capability.
SimpleGetApi simpleGetApi = RestClientBuilder.newBuilder().baseUri(getApplicationUri()).build(SimpleGetApi.class);
Is there other or better way to achieve this? Thanks.
While it is true, that the MP Rest CLient does not allow you to set the BaseUri dynamically when you use declarative/Injected clients, there are some (albeit hacky) ways how to achieve that.
One is to use standard ClientRequestFilter which can modify the URL:
#Provider
#Slf4j
public class Filter implements ClientRequestFilter {
#Inject RequestScopeHelper helper;
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (helper.getUrl() != null) {
URI newUri = URI.create(requestContext.getUri().toString().replace("https://originalhost.com", helper.getUrl()));
requestContext.setUri(newUri);
}
}
}
Where RequestScopeHelper is some help class (e.g. request scoped bean) through which you can pass the dynamic url, for example:
#Inject
RequestScopeHelper helper;
#Inject
#RestClient
TestIface myApiClient;
public void callSomeAPIWithDynamicBaseUri(String dynamic) {
helper.setUrl(dynamic);
myApiClient.someMethod();
}
Second is to use MP rest client SPI, namely the RestClientListener which allows you to modify the rest clients after they are built.
For this to work, you have to set the scope of your rest client to RequestScoped so that new instance is created for each request(if you use singleton for example, then the client is only created once and your listener will only be called once). This you can do via quarkus properties:
quarkus.rest-client."com.example.MyRestIface".scope=javax.enterprise.context.RequestScoped
public class MyListener implements RestClientListener {
#Override
public void onNewClient(Class<?> serviceInterface, RestClientBuilder builder) {
String newUri = //obtain dynamic URI from somewhere e.g. again request scope bean lookup, or maybe dynamic config source (create new in-memory ConfigSource, before you invoke your rest client set the corresponding rest client url property to your dynamic value, then inside this listener use ConfigProvider.getConfig().getProperty...)
builder.baseUri(URI.create(newUri));
}
}
Don't forget to register this listener as service provider(META-INF/services/org.eclipse.microprofile.rest.client.spi.RestClientListener)
Another option is to use custom CDI producer that would produce the Rest client instances for you; then you could control all client config yourself. You can use the RestClientBase from Quarkus rest client which is exactly what Quarkus uses under the hood during deployment phase to construct client instances. You will however have to duplicate all the logic related to registration of handlers, interceptors etc.
Do keep in mind, that any of these solutions will make the debugging and problem analysis more challenging - because you will now have multiple places, where the URI is controlled(MP config/quarkus properties, env vars, your custom impl...), so you need to be careful with your approach and maybe add some explicit log messages when you override the URI manually.
MicroProfile REST Client in Quarkus does allow you to use dynamic base URL with that simple "hack" :
Just put an empty String in #Path annotations for you API interface like that :
import javax.ws.rs.GET;
import javax.ws.rs.Path;
#Path("")
public interface SimpleGetApi {
#Path("")
#GET
String callWithDynmamicUrl(); //it can be String or any return type you want
}
After that you are ready to call your dynamic base URL :
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import java.net.URI;
public class Example {
public static void main(String[] args) {
URI anyDynamicUrl = URI.create("http://restcountries.eu/rest/some/dynamic/path");
SimpleGetApi simpleGetApi = RestClientBuilder.newBuilder().baseUri(anyDynamicUrl)
.build(SimpleGetApi.class);
simpleGetApi.callWithDynmamicUrl();
}
}

Does spring kafka support auto-deserialization in consumer side with no explicit type provided?

I'm using spring-integration-kafka.
I have an abstract interface Event, which has dozens of concrete implementations, say, AEvent, BEvent, CEvent, etc.. And I want one only consumer listener to handle all incoming Events, such as fun handle(message: Message<>) { message.payload... }
After reading the documentation, I find no way to support auto-deserialization with no explicit type provided in consumer side.
Any suggestion will be appreciated.
Using JdkSerializationRedisSerializer from spring-data-redis meet my requirements.
public class GenericObjectSerializer implements Serializer<Object> {
private final JdkSerializationRedisSerializer serializer =
new JdkSerializationRedisSerializer();
}
public class GenericObjectDeserializer implements Deserializer<Object> {
private final JdkSerializationRedisSerializer serializer =
new JdkSerializationRedisSerializer();
}

Jaxb setting dynamic #XmlRootElement with Spring Web Services

I have a Spring application that consumes a SOAP web services. I have several classes that are quite simple and only differ in the #XmlRootElement. I'm wondering if there's a way to create a more generic class that I can set the root element on dymanically.
Here's a few of the classes with only the root element being different.
#XmlRootElement(name="safetydate")
public class SafetyDateRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checkallsafety")
public class SafetyGetAllRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checksafetyupdates")
public class SafetyGetUpdatesRequest extends Carrier411RequestImpl {
}
In another class, I'm processing these classes in the following fashion:
private void sendRequest(Carrier411Request request, Carrier411ResponseHandler responseHandler) throws FaultCodeException {
Carrier411Response response = (Carrier411Response) ws.marshalSendAndReceive(registry.get(request.getClass()), request);
checkResponseForFault(response);
responseHandler.handleResponse(request, response);
}
I know there's another version of marshalSendAndReceive that accepts a callback allowing you to modify the request before actually sending it, but I haven't figured out how to achieve what I'm trying to do.

Resources