Identifying multiple STOMP endpoints in message controller - spring

Is it possible to route different STOMP endpoints for each #MessageMapping?
For example, if I set my WebSocketMessageBrokerConfigurer like this:
#EnableWebSocketMessageBroker
#Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ep1", "/ep2").setAllowedOriginPatterns("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
}
Then, how can I specify /ep1 & /ep2 for each #MessageMapping in my controller?

Related

When websocket connected to server via domen, Web socket status finished, if connected via ip addres it works

Spring boot application and used Spring web socket with Stomp. Is there anyone who faced to this problem?
My socket config:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").setAllowedOriginPatterns("*").withSockJS();
}
}
And connected with ip address:
and if I try with domen:

Intercept request & send to external

I am developing a Spring boot project.
One example of my controller:
#Controller
public class RestController {
#GetMapping(value = "/student/{studentId}")
public #ResponseBody Student getData(#PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);
return student;
}
}
I have other endpoints implemented as well.
I need to intercept every request hits my endpoints & forward the request to another service (microservice), in other words, I need to forward each request to another web app running on the same local machine as current one, based on the response from that service to decide whether proceed forward the request or not.
My rough idea is to use HandlerIntercept , but I am not sure whether I am going to the right direction. Could someone please share some experiences what is the best way to achieve this? It would be nice if you could show some sample code. Thanks in advance.
You can use HandlerInterceptorAdapter.
Define the Interceptor as below.
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
System.out.println("In preHandle we are Intercepting the Request");
System.out.println("____________________________________________");
//Call the Rest API and Validate
if (conditionsNotMet()) {
response.getWriter().write("something");
response.setStatus(someErrorCode);
return false;
}
}
}
Register the HandlerInterceptorAdapter
#Configuration
public class PathMatchingConfigurationAdapter extends WebMvcConfigurerAdapter {
#Autowired
private RequestInterceptor requestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInterceptor);
}
}
using WebMvcConfigurer
#Configuration
public class PathMatchingConfigurationAdapter implements WebMvcConfigurer {
#Autowired
private RequestInterceptor requestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInterceptor);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
}
#Override
public void addCorsMappings(CorsRegistry corsRegistry) {
}
#Override
public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {
}
#Override
public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {
}
#Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> list) {
}
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> list) {
}
#Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
}
#Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
}
#Override
public Validator getValidator() {
return null;
}
#Override
public MessageCodesResolver getMessageCodesResolver() {
return null;
}
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
#Override
public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {
}
#Override
public void addFormatters(FormatterRegistry formatterRegistry) {
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
}

How to troubleshoot and resolve 404 on SockJs's /info path when with cross-origin

I'm having trouble with SockJs and CORS. I use spring. I set up the WebMvcConfigured as follows:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowCredentials(true);
;
}
};
}
and WebSocketConfig as follows:
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/gs-guide-websocket")
.setAllowedOrigins("*")
.withSockJS();
}
However, when my web client tries to GET against /gs-guide-websocket/info , it gets a 404.
SockJs's specification requires a /info path to be present. It seems like even though I did use .withSockJS() on the server side, it did not set up the /gs-guide-websocket/info path.
How should I create this path through spring and/or spring-websocket?
Thank you,
Kevin
I am not using the STOMP protocol, whereas I have configured the websocket with SockJS which is working fine for me.
Here the message payload has sent as response to the frontend.
CustomWebSocketHandler.java
#Component
public class CustomWebSocketHandler extends TextWebSocketHandler {
#Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("message", "Session started");
jsonObject.addProperty("payload", payload);
session.sendMessage(new TextMessage(new Gson().toJson(jsonObject)));
}
}
WebSocketConfig.java
#EnableWebSocket
#Configuration
public class WebSocketConfig implements WebSocketConfigurer {
#Autowired
private CustomWebSocketHandler customWebSocketHandler;
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry
.addHandler(customWebSocketHandler, "/socket")
.setAllowedOrigins("*")
.withSockJS()
.setHeartbeatTime(20);
}
}

Spring Websocket Configuration: using WebSocketMessageBrokerConfigurationSupport and WebSocketConfigurer together - how?

I am configuring currently my Spring Websocket using the class
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport
now I came across the advice Spring STOMP Websockets: any way to enable permessage-deflate on server side?
that makes use of
public class SampleJettyWebSocketsApplication implements WebSocketConfigurer
and overrides
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry)
and offers
#Bean
public DefaultHandshakeHandler handshakeHandler()
Question, what is the relation between WebSocketConfigurer and WebSocketMessageBrokerConfigurationSupport? In other words, can I possibly somehow add configuration from WebSocketConfigurer implementation via API of the first class, WebSocketMessageBrokerConfigurationSupport, so all configuration remains in one single file?
The WebSocketMessageBrokerConfigurationSupport implementation is DelegatingWebSocketMessageBrokerConfiguration which is configured via #EnableWebSocketMessageBroker. All you need in your custom code is WebSocketMessageBrokerConfigurer implementation. And that one is injected into DelegatingWebSocketMessageBrokerConfiguration:
#Autowired(required = false)
public void setConfigurers(List<WebSocketMessageBrokerConfigurer> configurers) {
This is a sample config from my test-cases:
#Configuration
#EnableWebSocketMessageBroker
static class ServerConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Bean
public DefaultHandshakeHandler handshakeHandler() {
return new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy());
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setHandshakeHandler(handshakeHandler())
.setAllowedOrigins("http://foo.com")
.addInterceptors(new HandshakeInterceptor() {
#Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
return request.getHeaders().getOrigin() != null;
}
#Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Exception exception) {
}
})
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry configurer) {
configurer.setApplicationDestinationPrefixes("/app")
.enableSimpleBroker("/topic", "/queue");
}
}

Where is SpringBootServletInitializer's DispatcherServlet?

How SpringBootServletInitializer determines RootConfig.class, WebConfig.class, and maps DispatcherSevlet?
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
return application.sources(Application.class); - loads the Application.class. That's your main configuration, where you can declare #Beans. You can add more #Configuration classes by putting them in the same folder, for example, and they will be "component-scanned".
If you declare a #Configuration class that extends WebMvcConfigurerAdapter, you have an access to the web configuration like resource handlers, argument resolvers, etc.
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public-resources/")
.setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new FooBarHandlerMethodArgumentResolver());
}
}
By default the dispatcher servlet is configured to the root path "/"
If you need more details, see the auto configuration.

Resources