Hi I am working on android app in which I have integrated bigquery. I see sometimes we are getting a lot of SSL exceptions while inserting data to big query tables. I don't know how to handle this . Please help what exactly is the cause of this problem. Here is the same thread but no answer Bigquery SSL error while doing streaming insert api call
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946) ~[na:1.7.0_51]
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) ~[na:1.7.0_51]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) ~[na:1.7.0_51]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) ~[na:1.7.0_51]
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) ~[na:1.7.0_51]
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) ~[na:1.7.0_51]
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091) ~[na:1.7.0_51]
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250) ~[na:1.7.0_51]
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:77) ~[google-http-client-1.19.0.jar:1.19.0]
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:965) ~[google-http-client-1.19.0.jar:1.19.0]
at com.google.api.client.googleapis.batch.BatchRequest.execute(BatchRequest.java:241) ~[google-api-client-1.19.1.jar:1.19.1]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$2$$anonfun$4.apply(InsertApiActor.scala:131) ~[analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$2$$anonfun$4.apply(InsertApiActor.scala:118) ~[analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.common.store.bigquery.api.BigQueryApi$.withSyncClient(BigQueryApi.scala:71) ~[analytics-common_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$2.apply$mcV$sp(InsertApiActor.scala:118) ~[analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$2.apply(InsertApiActor.scala:115) ~[analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$2.apply(InsertApiActor.scala:115) ~[analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.common.monitoring.Timer.time(Timer.scala:15) ~[analytics-common_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor.com$livestream$analytics$datastorage$worker$InsertApiActor$$insertDataRowsToBigQueryTable(InsertApiActor.scala:115) [analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at com.livestream.analytics.datastorage.worker.InsertApiActor$$anonfun$receive$1.applyOrElse(InsertApiActor.scala:80) [analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at akka.actor.Actor$class.aroundReceive(Actor.scala:465) [akka-actor_2.11-2.3.9.jar:na]
at com.livestream.analytics.datastorage.worker.InsertApiActor.aroundReceive(InsertApiActor.scala:54) [analytics-data-storage-worker_2.11-1.0.0.jar:1.0.0]
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516) [akka-actor_2.11-2.3.9.jar:na]
at akka.actor.ActorCell.invoke(ActorCell.scala:487) [akka-actor_2.11-2.3.9.jar:na]
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:254) [akka-actor_2.11-2.3.9.jar:na]
at akka.dispatch.Mailbox.run(Mailbox.scala:221) [akka-actor_2.11-2.3.9.jar:na]
at akka.dispatch.Mailbox.exec(Mailbox.scala:231) [akka-actor_2.11-2.3.9.jar:na]
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library-2.11.5.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.11.5.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.5.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.5.jar:na]
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482) ~[na:1.7.0_51]
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927) ~[na:1.7.0_51]
... 30 common frames omitted
Probably the server is asking for a client certificate and you aren't providing one. The server will provide a list of trusted signers, and your client certificate needs to be signed by one of those. You can't use a self-signed certificate for the client unless you've made special arrangements with the server, i.e. imported your client certificate into its trusted certificate list. Your SSL client won't send a certificate if it can't find one, or if the one(s) that it finds don't have trusted signers.
It doesn't have anything to do with what the SSL connection was going to do after it was established, e.g. SQL queries, updates, etc.
If you are using (https) requests you need to add Security Certificate in your app. here is link how to add it.
http://stackoverflow.com/questions/4065379/how-to-create-a-bks-bouncycastle-format-java-keystore-that-contains-a-client-c
You can test if indeed security certificate is causing it, Add this class in your project.
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
#Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
and call
HttpsTrustManager.allowAllSSL(); // Allow all SSL connections
before an API call.
NOTE:
This code skips verification and allows any certificate to work.
This method should not be used for secure communication.
This is just to check if Certificate authentication is causing the error.
Related
I have oauth2 + jwt authorization in my project.
#Component
#RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().disable()
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
}
#Slf4j
#Configuration
public class JwtConfiguration {
#Value("${app.security.jwt.keystore-location}")
private String keyStorePath;
#Value("${app.security.jwt.keystore-password}")
private String keyStorePassword;
#Value("${app.security.jwt.key-alias}")
private String keyAlias;
#Bean
public KeyStore keyStore() {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(keyStorePath);
keyStore.load(resourceAsStream, keyStorePassword.toCharArray());
return keyStore;
} catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
log.error("Unable to load keystore: {}", keyStorePath, e);
}
throw new IllegalArgumentException("Unable to load keystore");
}
#Bean
public RSAPublicKey jwtValidationKey(KeyStore keyStore) {
try {
Certificate certificate = keyStore.getCertificate(keyAlias);
PublicKey publicKey = certificate.getPublicKey();
if (publicKey instanceof RSAPublicKey) {
return (RSAPublicKey) publicKey;
}
} catch (KeyStoreException e) {
log.error("Unable to load private key from keystore: {}", keyStorePath, e);
}
throw new IllegalArgumentException("Unable to load RSA public key");
}
#Bean
public JwtDecoder jwtDecoder(RSAPublicKey rsaPublicKey) {
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(rsaPublicKey).build();
OAuth2TokenValidator<Jwt> validator = new Validator();
jwtDecoder.setJwtValidator(validator);
return jwtDecoder;
}
class Validator implements OAuth2TokenValidator<Jwt> {
OAuth2Error error = new OAuth2Error("error", "error description", null);
#Override
public OAuth2TokenValidatorResult validate(Jwt jwt) {
......
return OAuth2TokenValidatorResult.success();
}
}
}
i followed example(https://medium.com/swlh/stateless-jwt-authentication-with-spring-boot-a-better-approach-1f5dbae6c30f) and used jks for keys, in this case everything works. In my case, this approach of using jks is not suitable and i need to use kid.crt. The most interesting thing is that kid is the name of the file and it matches the kid field in the jwt header. That is, having received the kid field from the header, we should get a file that looks like kid.crt. I don't know how to get rid of jks in favor crt. How to create such a .crt? and how to configure at what point to take the file with the key?
jks I created this way
keytool -genkey -alias jwtsigning -keyalg RSA -keystore keystore.jks -keysize 2048
my application.properties
app.security.jwt.keystore-password=password
app.security.jwt.key-alias=jwtsigning
app.security.jwt.keystore-location=keys/keystore.jks
dependecies
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
The key that you need to validate an incoming JWT should come from the Authorization Server which issued you the JWT. You don't create it yourself, unless you are also in control of the Authorization Server, then you had to create a pair of private and public key. The private key is used to sign JWTs, and the public key should be distributed to APIs, so they can validate JWTs.
A perfect way is when the Authorization Server exposes a JWKS endpoint where your API can download the relevant key from. If this isn't possible in your case and you really need the key file, then you should get it from whoever manages the Authorization Server. You can then have a look e.g. here: Adding .crt to Spring Boot to enable SSL on how to add a crt into a keystore. Once you have the keystore, the code you have should work.
Problem:
I am using MFP 7.1 and oauth.tai_1.0.0.jar in my android application for app authenticity and have defined the realm on MFP's end. Each time I try to register to the application I see in the log
OAuthTAI Authentication failed with Status = 401, WWW-Authenticate: Bearer realm="imfAuthentication", scope="UserAuthRealm"
This is not preventing the application flow. I am only getting this error in the log and this error is seen before the realm class's init method is initialized and after that everything works fine.
I am wondering why I am getting this error.
Analysis:
I have checked the challenge handler in android, it is fine. I also did a fresh installation of the app in order to be sure of a new access token being sent from MFP.
I had also checked in MFP' Oauth jar and checked the 401 error case, it checks for invalid_token and invalid_authorization. But in my case, none of these two are there as I am not getting this in error description. I have the custom authenticator class defined which is mapped to UserAuthReal, code below:
CustomUserAuthenticator.java
package com.ibm.mfp;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.worklight.core.auth.impl.AuthenticationContext;
import com.worklight.server.auth.api.AuthenticationResult;
import com.worklight.server.auth.api.AuthenticationStatus;
import com.worklight.server.auth.api.MissingConfigurationOptionException;
import com.worklight.server.auth.api.UserIdentity;
import com.worklight.server.auth.api.WorkLightAuthenticator;
public class CustomUserAuthenticator implements WorkLightAuthenticator {
private static final long serialVersionUID = -548850541866024092L;
private static final Logger logger = Logger.getLogger(CustomUserAuthenticator.class.getName());
private String pin;
private String userName;
private String uniqueID;
private String userNumber;
private String userAuthFlag;
private String registrationNumber;
protected Map<String, Object> authenticationData;
public void init(Map<String, String> options) throws MissingConfigurationOptionException {
logger.info("CustomUserAuthenticator initialized");
}
public AuthenticationResult processRequest(HttpServletRequest request, HttpServletResponse response,
boolean isAccessToProtectedResource) throws IOException, ServletException {
String clientID = AuthenticationContext.getCurrentClientId();
logger.info("CustomUserAuthenticator :: processRequest : clientID : " + clientID);
String requestURI = request.getRequestURI();
logger.info("CustomUserAuthenticator :: processRequest : request.getRequestURI() :" + requestURI);
String requestQueryString = request.getQueryString();
requestQueryString = null;
logger.info("CustomUserAuthenticator :: processRequest : request.getQueryString() :" + requestQueryString);
// Request the epin from the user
if (request.getRequestURI().contains("/ADIBMBA/auth/v2/auth")) {
this.pin = request.getParameter("pin");
this.userName= request.getParameter("userName");
this.uniqueID = request.getParameter("uniqueID");
this.userNumber = request.getParameter("userNumber");
this.userAuthFlag = request.getParameter("userAuthFlag");
this.registrationNumber = request.getParameter("registrationNumber");
if (null != this.customerNumber) {
logger.info(
"CustomUserAuthenticator :: processRequest : request.getRequestURI() : getParameter customerNumber : "
+ this.customerNumber);
}
if (null != pin && pin.length() > 0) {
return AuthenticationResult.createFrom(AuthenticationStatus.SUCCESS);
} else {
response.setContentType("application/json; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().print("{\"authStatus\":\"required\", \"errorMessage\":\"Please enter epin\"}");
return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED);
}
}
if (!isAccessToProtectedResource) {
return AuthenticationResult.createFrom(AuthenticationStatus.REQUEST_NOT_RECOGNIZED);
}
response.setContentType("application/json; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().print("{\"authStatus\":\"required\"}");
return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED);
}
public boolean changeResponseOnSuccess(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String requestURI2 = request.getRequestURI();
logger.info("CustomUserAuthenticator :: changeResponseOnSuccess : request ");
logger.info("CustomUserAuthenticator :: changeResponseOnSuccess : response ");
// first worked partially with if
// (request.getRequestURI().contains("/ADIBMBA/auth/v2/auth")){
if (request.getRequestURI().contains("/ADIBMBA/mainapps/services/apis/App/iOSnative")
|| (request.getRequestURI().contains("/ADIBMBA/auth/v2/auth"))) {
response.setContentType("application/json; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().print("{\"authStatus\":\"complete\"}");
return true;
}
return false;
}
public AuthenticationResult processAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
String errorMessage) throws IOException, ServletException {
logger.info("CustomUserAuthenticator :: processAuthenticationFailure");
response.setContentType("application/json; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().print("{\"authStatus\":\"failed\", \"errorMessage\":" + errorMessage + ","
+ (String) authenticationData.get("error") + "}");
return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED);
}
public AuthenticationResult processRequestAlreadyAuthenticated(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
logger.info("CustomUserAuthenticator :: processRequestAlreadyAuthenticated");
return
AuthenticationResult.createFrom(AuthenticationStatus.
REQUEST_NOT_RECOGNIZED);
}
public Map<String, Object> getAuthenticationData() {
authenticationData = new HashMap<String, Object>();
authenticationData.put("userName", userName);
authenticationData.put("uniqueID", uniqueID);
authenticationData.put("pin", pin);
authenticationData.put("userNumber", userNumber);
authenticationData.put("userAuthFlag", userAuthFlag);
authenticationData.put("registrationNumber", registrationNumber);
return authenticationData;
}
public HttpServletRequest getRequestToProceed(HttpServletRequest request, HttpServletResponse response,
UserIdentity userIdentity) throws IOException {
return null;
}
#Override
public WorkLightAuthenticator clone() throws CloneNotSupportedException {
CustomUserAuthenticator otherAuthenticator = (CustomUserAuthenticator) super.clone();
return otherAuthenticator;
}
}
Summary:
If the application flow is normal then why i am getting this OAuthTAI 401 error in log. Suppose If it is a problem related to token & id token then i should not be able to access protected resource data. Application should not allow me to proceed further.
From the description and comments, it appears you have mixed up Liberty's OAuth TAI and MFP's OAuth security model.
MFP's OAuth security model is used to protect MFP resources ( adapters and runtime endpoints), while Liberty's OAuth TAI is to protect resources deployed on Liberty server ( eg: web applications).
The link you followed details steps using which MFP server can act as the OAuth server for resources deployed in Liberty server.
From the description and the custom Authenticator that extends WorklightAuthenticator you are depending on the security validation to be done by MFP's security framework. If the requirement is for your MFP adapters to be protected by OAuth security and the device begins by obtaining an OAuth token from MFP server, then you should use MFP's OAuth security and not resort to Liberty OAuth TAI. MFP's OAuth security framework works out of the box, without any need to configure TAI.
Refer to the following links for a better understanding and working samples:
a) MFP OAuth security model
b) Java adapters
c) Custom Authenticator
I've been experiencing troubles with spring-boot consumer. I compared the work of two consumers.
First consumer:
import com.rabbitmq.client.*;
import java.io.IOException;
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
Second consumer:
#Controller
public class Consumer {
#RabbitListener(queues = "hello")
public void processMessage(Message message) {
}
}
There are no config files for spring-boot consumer installed, everything goes by default.
On my computer first one works 10 times faster. What might be the problem?
The default prefetch (basicQos) for Spring AMQP consumers is 1 which means only 1 message is outstanding at the consumer at any one time; configure the rabbitListenerContainerFactory #Bean to set the prefetchCount to something larger.
You will have to override the default boot-configured #Bean.
Even though this is not described in the Spring documentation, a websocket connect should lead to a connection upgrade response (101 status).
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig<S extends ExpiringSession> extends AbstractSessionWebSocketMessageBrokerConfigurer<S>{
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/mobile-server");
config.setUserDestinationPrefix("/mobile-user");
}
#Override
public void configureStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
.setAllowedOrigins("*")
.withSockJS()
.setSessionCookieNeeded(false)
;
}
}
However, I get a 200 status with a "Welcome to SockJS" message which is generated by TransportHandlingSockJsService in stead of the WebSocketHttpRequestHandler which would generate the upgrade AFAIK
#Configuration
public class WebSocketSecurity extends AbstractSecurityWebSocketMessageBrokerConfigurer{
#Override
protected boolean sameOriginDisabled() {
return true;
}
#Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.nullDestMatcher().permitAll()
.simpSubscribeDestMatchers("/user/queue/errors").permitAll()
.simpDestMatchers("/mobile-server/**").hasRole("ENDUSER")
.simpSubscribeDestMatchers("/user/**", "/topic/**").hasRole("ENDUSER")
.anyMessage().denyAll();
}
}
When I change the config to
#Override
public void configureStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
.setAllowedOrigins("*");
}
to my surprise a call to /ws does lead to a connection upgrade 101. I'm surprised, since the documentation and all examples uniformly use the withSockJS() and the start of any websocket connection AFAIK is a request upgrade.
I can choose to force the upgrade by connecting to /ws/websocket (also not documented). So, I'm not sure what is best.
Any suggestions?
This is expected behavior. It's how the SockJS protocol works:
http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html. There is an initial "greeting" request and then the client starts trying transports one at a time.
I have stability problems with Spring web-sockets. Sometimes I have a similar exception to that describe in https://jira.spring.io/browse/SPR-12812.
The patch is not available, then I have implemented my own code with a custom SubProtocolWebSocketHandler.
public class WBSSubProtocolWebSocketHandler extends SubProtocolWebSocketHandler {
private static final Logger LOG = LoggerFactory.getLogger(WBSSubProtocolWebSocketHandler.class);
public WBSSubProtocolWebSocketHandler(MessageChannel clientInboundChannel, SubscribableChannel clientOutboundChannel) {
super(clientInboundChannel, clientOutboundChannel);
}
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
super.afterConnectionClosed(session, status);
LOG.debug("WebSocket Connection closed for client with session ID {}", session.getId());
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// WebSocketHandlerDecorator could close the session
// https://jira.spring.io/browse/SPR-12812
if (!session.isOpen()) {
LOG.warn("WebSocket Connection established for client with session ID {} was closed.", session.getId());
return;
}
super.afterConnectionEstablished(session);
LOG.debug("WebSocket Connection established for client with session ID {}", session.getId());
}
#Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
super.handleTransportError(session, exception);
LOG.warn("WebSocket transport error for client with session ID {}", session.getId());
}
#Override
public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception {
super.handleMessage(session, message);
LOG.debug("Websocket incoming message ({}) from client with session ID {}", message.getPayload().toString(), session.getId());
}
#Override
public void handleMessage(Message message) throws MessagingException {
super.handleMessage(message);
LOG.debug("Websocket incoming message : {}, header {}", message);
}
}
Now my problem is to reproduce the exception to see if the problem is solved. I tried various ways, but without success. I can not reproduce the closing of the connection. Does anyone have an idea?
We also have a second problem. The client application (angularjs application) sometimes reports that the socket-web connection is lost. But I do not understand why because on the server I have no error / warning in the logs.
How can I identify the problem and reproduce it?