Spring Boot + Sockjs client offline connecting issues - spring-boot

I'm trying to connect a Spring Boot Stomp Server with multiple sockjs clients offline but I get the warning
Websocket is closed before the connection is established
followed by
GET http://192.168.1.45:8080/socket/327/si5osugt/jsonp?c=jp.a3xdefl net::ERR_ABORTED 404 (Not Found)
I'm using Spring Boot Version 2.1.2 with the spring-boot-starter-websocket package on the backend side and on the frontend side I'm using Angular 6 with sockjs-client version 1.3.0. Frontend and backend are both running on port 8080
I'm getting some errors while turning the internet down. If the internet is turned off the iframe tries to reach to https://cdn.jsdelivr.net/npm/sockjs-client#1/dist/sockjs.js.
I managed by configuring stomp server on the backend to set the client library by adding .setClientLibraryUrl to a absolute path which is offline reachable.
registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS).setClientLibraryUrl("http://192.168.1.45/dist/sockjs.min.js");
and get a 200 OK on http://192.168.1.45/dist/sockjs.min.js
Spring Boot:
WebSocketConfiguration (extends AbstractWebSocketMessageBrokerConfigurer)
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOrigins("*")
.withSockJS().setClientLibraryUrl("http://192.168.1.45/dist/sockjs.min.js");
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
MessageBrokerRegistry messageBrokerRegistry = registry.setApplicationDestinationPrefixes("/app");
messageBrokerRegistry.enableSimpleBroker( "/test", "/test2"
);
}
WebSocketController
private final SimpMessagingTemplate template;
#Autowired
WebSocketController(SimpMessagingTemplate template){
this.template=template;
}
#MessageMapping("/send/message")
public void onReceivedMessage( String destination , String message){
this.template.convertAndSend(destination , message);
}
public void convertAndSend(String url, Object o){
this.template.convertAndSend(url, o);
}
Angular 6:
TestComponet
ngAfterViewInit() {
let ws = new SockJS('http://192.168.1.45:8080/socket');
this.stompClient = Stomp.over(ws);
let that = this;
that.stompClient.subscribe("/test", (message) => {
if (message.body) {
console.log(message.body);
}
});
that.stompClient.subscribe("/test2", (message) => {
if (message.body) {
console.log(message.body);
}
});
}
I thought it would work by just adding the sockjs client lib to an offline reachable path but I get the warning
Websocket is closed before the connection is established
followed by
"GET http://192.168.1.45:8080/socket/327/si5osugt/jsonp?c=jp.a3xdefl net::ERR_ABORTED 404 (Not Found)"
The library works with an internet connection perfectly fine, but I need it to work with both situations online and offline.

I had the same issue, and I fixed it by removing SockJs.
So now I'm currently using only Stomp-Websockets.
Changes in SpringBoot-Service(WebsocketConfiguration):
registry.addEndpoint("/justStomp").setAllowedOrigins("*");
I removed the .withSockJS() and .setClientLibraryUrl(../sockjs.min.js)
Changes in my Javascript-Code to connect to the websocket:
const stompClient = Stomp.client(`ws://localhost:8080/justStomp`);
stompClient.heartbeat.outgoing = 0;
stompClient.heartbeat.incoming = 0;
stompClient.connect({ name: 'test' }, frame => this.stompSuccessCallBack(frame, stompClient), err => this.stompFailureCallBack(err));
Instead of using Stomp.over(sockjs) I use the Stomp.client Method to directly connect to the websocket-url.
I have a rabbitMQ in the background with stomp-plugin, and this only works properly with the 2 heartbeat-settings. see here RabbitMQ Web STOMP without SockJS

Related

Websocket not working on GAE (Google App Engine)

I am using websocket in my spring boot + react application which was working fine ,Now i am deploying that application on GAE( it has four instance and can extend up to 6 instance).
But here websocket is not working fine as it should.
websocket connection is getting created but response is not coming from backend if i refresh the page then sometimes it works and if refresh again then it does't work.
Below is the Reference code to create websocket connection in React js :-
#action connectToWebSocket = (channelName) => {
this.webSocketInitilization();
this.stompClient.connect({}, this.connectSocket, this.onError);
}
#action webSocketInitilization = () => {
this.socket = new SockJS('/wss');
this.stompClient = Stomp.over(this.socket);
this.stompClient.debug = null
}
connectSocket = () => {
this.subscription = this.stompClient.subscribe("/topic/model_" + this.modelId, this.onMessageReceived);
console.log("connection created");
}
Backend configuration file :-
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/wss").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic"); // Enables a simple in-memory broker
}
}
Not sure what's the issue may be something related to GAE configuration ?
Edited :- Adding app.yml file
runtime: java
env: flex
resources:
memory_gb: 6.5
cpu: 4
disk_size_gb: 20
automatic_scaling:
min_num_instances: 4
max_num_instances: 8
cpu_utilization:
target_utilization: 0.6
handlers:
- url: /.*
script: this field is required, but ignored
network:
session_affinity: true
I researched on that,so people was saying this parameter session_affinity: true will work in beta version only, earlier i had another version so i updated my version but still this parameter is not getting reflected in my app engine config.
Regarding error logs :- Surprisingly i am not getting any error logs on browser console and not in GAE logs.
Any help ?

retrofit spring boot not responding

I have a server in spring boot, which is running on port 8080.
Now I'm trying to call rest api in my android application using retrofit2.
Here is what I have implemented:
final TextView textView=findViewById(R.id.t1);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
Call<TC> call = jsonPlaceHolderApi.getPosts();
call.enqueue(new Callback<TC>() {
#Override
public void onResponse(Call<TC> call, Response<TC> response) {
textView.setText(response.toString());
if (!response.isSuccessful()) {
return;
}
TC posts = response.body();
textView.setText(posts.toString());
}
#Override
public void onFailure(Call<TC> call, Throwable t) {
}
});
I can surly say that, it's not working as my api is not even being called. As the hello world screen remains as it is.
And in my server I have logger, which doesn't log anything, so it doesn't get called.
Here is my CORS:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("*")
.allowedOrigins("*");
}
};
}
The problem is with the word localhost.
As for debugging purpose I'm connecting the android device with my PC so my android device can't connect to localhost as it is just an alias of my IP address.
To resolve this, I opened up CMD and wrote ipconfig, by this command I can see all details related to IP.
And here it shows my IPv4 address as $.$.$.$. I just replaced the localhost with that $.$.$.$.
Now everything is working fine.
Any ideas how to make it work with Asp.net core. I just test it wih my local machine ip address and work perfectly.
Unfortunately, not the case with Asp.net core.
aAndroid + Retrofit + Asp.net API "java.security.cert.CertPathValidatorException: Trust anchor for certification path not found."

Can my Spring Boot application run HTTPS only on certain #RequestMappings?

I'm working on a Spring application that is for a smart house. I got the micro-controllers that send data to the Spring application, but I can not implement SSL on them on account of not enough space and processing speed.
On the client-side, I want to use HTTPS, because the client runs on Android.
Can I map certain requests to HTTP and others to HTTPS?
Can we not open two ports from the spring boot application one on 443 other on 80. So that, on https it listens to 443 and on http to 80. So in your app you can configure http on a url to use 80 port and https to use 443 port.
We can do this by, changes in application.properties:
#Https settings
server.port=443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = secret
#Http setting
server.http.port=80
I am giving an example using Undertow server, you can do this on any application server (tomcat, etc):
#SpringBootApplication
public class Boot {
#Value("${server.http.port:0}")
private Integer httpPort;
public static void main(String[] args) throws Exception {
SpringApplication.run(Boot.class, args);
}
#Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
public void customize(Builder builder) {
// worker options
builder.setWorkerThreads(500);
builder.setWorkerOption(Options.TCP_NODELAY, true);
// io options
builder.setIoThreads(Runtime.getRuntime().availableProcessors() * 2);
// socket options
builder.setSocketOption(Options.BACKLOG, 10000);
builder.setSocketOption(Options.TCP_NODELAY, true);
builder.setSocketOption(Options.REUSE_ADDRESSES, true);
// server options
builder.setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false);
builder.setServerOption(UndertowOptions.ALWAYS_SET_DATE, true);
builder.setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false);
// Done to keep both http and https port open at production
if (httpPort > 0)
builder.addHttpListener(httpPort, "0.0.0.0");
}
});
return factory;
}
}

SockJS + Stomp + SpringBoot = Issue

I have an application with a page that subscribe a websocket endpoint with this:
var socket = new SockJS("/hello");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe('/topic/nextticket', function (ws_response) {
var data = JSON.parse(ws_response.body);
....
});
});
This app run on Raspberry and all works fine when the raspberry is connected on internet. But in a local network (no Internet) I have this
My backend conf is:
#Configuration
#PropertySource("file:/etc/app.properties")
#EnableWebSocketMessageBroker
class MessageBroker extends AbstractWebSocketMessageBrokerConfigurer {
#Autowired
Environment env
#Override
void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic")
config.setApplicationDestinationPrefixes("/app")
}
#Override
void registerStompEndpoints(StompEndpointRegistry registry) {
def ip = env.getProperty("kiosk.ip") ? env.getProperty("kiosk.ip") as String : "192.168.1.90"
registry.addEndpoint("/hello")
.setAllowedOrigins("*")
.withSockJS()
.setClientLibraryUrl("http://${ip}:8080/js/sockjs.js")
}
}
I don't understand why have a CORS (I suppose) problem.. And the page reload forever.
Thanks in advance
Luis
I had this CORS behaviour in my application whenever I used a specific IP.
application.properties
server.address: 192.168.1.90
After removing server.address from the application.properties the application worked as expected. If somebody knows the cause of this please let me know. I would have expected that
registry.setAllowedOrigins("*")
would remove all CORS behaviour as document here

WebSocket can connect to local server, but can't send or receive

I'm working on setting up a websocket between two local servers for development.
On one end I have my Ionic app running on http://localhost:8100/
On the other end I have a Spring backend running on http://localhost:9080/ (or http://127.0.0.1:9080)
Connection has been established, so next up I want to send a message to the websocket with a token (I know this can be send along when the connection is set up in SockJS 1.1.0, but I am currently using 0.3.4)
However my code in the backend doesn't seem to respond, I am wondering if my IP configuration is correct. I followed a tutorial and got this working in another project.
Anyone with more experience that knows if the url in the subscribe function also needs to be prefixed with 'localhost' or an IP adrress? I know the websocket changes from http:// to ws:// so I suppose when this is the case I need to prefix it with something like: ws://localhost:9080/...
Anyway, here's my code:
WebSocet Service :
function init() {
var socket = new SockJS('http://127.0.0.1:9080/ws-notification');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('Connected: ' + frame);
/**
* Subscribe at /ws-topic/greetings url to catch messages
*/
stompClient.subscribe('/ws-topic/greetings', function(greeting){
notify(JSON.parse(greeting.body).content);
});
parseAuthentication();
});
}
function parseAuthentication(){
stompClient.send("/ws-app/ws-notification",{},JSON.stringify({ 'token': authenticationService.isAuthenticated() }));
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
// setConnected(false);
console.log("Disconnected");
}
function notify(message){
console.log("NOTIFY: "+message);
}
The WebSocket Config :
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-notification").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config){
config.enableSimpleBroker("/ws-topic");
config.setApplicationDestinationPrefixes("/ws-app");
}
}
My Controllerfunction :
#MessageMapping("/ws-notification")
#SendTo("/ws-topic/greetings")
public Notify greeting(Notify notify) throws InterruptedException {
Thread.sleep(1000);
return new Notify("Hello, your token is :" + notify.getWsToken());
}
Notice that I only specify the IP adress when I set up the connection in the init() function, tried to prefix the other url's with ws://127.0.0.1:... but no luck!
I found the answer!
The problem was that there was no default contructor method in the models I used to send the data.
This was also not implemented or mentioned in the Spring WebSocket Tutorial

Resources