Is there any way to do interception or authentication of request async? For example in flow like this: get password from user, use it to obtain token an then retry the call that was intercepted?
I have the same problem here.
I use wait()and notify() in the getToken method in my code, but because i use OkHttp in Retrofit library, it is creating a new thread and makes it possible to have async operations here.
public synchronized void getToken() throws InterruptedException {
if (!isRefreshing()) {
//This is very important to call notify() on the same object that we call wait();
final TokenProvider myInstance = this;
setRefreshing(true);
Log.d("refreshToken", "Refreshing token..." );
//Make async call
getRestClient().getAccountService().getRefreshedToken(mLoginData.getRefreshToken())
.subscribe(new Observer<LoginResponse>() {
#Override
public void onCompleted() {
synchronized (myInstance) {
setRefreshing(false);
Log.d("refreshToken", "notifyAll onComplete.");
myInstance.notifyAll();
}
}
#Override
public void onError(Throwable e) {
synchronized (myInstance) {
setRefreshing(false);
myInstance.notifyAll();
Log.d("refreshToken", "onError .");
}
}
#Override
public void onNext(LoginResponse loginResponse) {
synchronized (myInstance) {
mLoginData = loginResponse;
Log.d("refreshToken", "notifyAll onNext .");
myInstance.notifyAll();
}
}
});
}
Log.d("refreshToken", "before wait ." + android.os.Process.getThreadPriority(android.os.Process.myTid()) + this.toString());
this.wait();
Log.d("refreshToken", "after wait ." + android.os.Process.getThreadPriority(android.os.Process.myTid()) + this.toString());
}
You can try if this works for you.
Related
Two Springboot microservices need to interact with each other to achieve mass emailing feature. Microservice 1: CollectorService collects information about clients and
Microservice 2: NotificationService to send documents via SMTP service. NotificationService is unable to handle the load that CollectorService produces. Now I want to understand how NotificationService can signal CollectorService to slow down. My code looks like below currently.
CollectorSerivce calling NotificationService
final WebClient client = WebClient.builder().baseUrl(BASE_URL.get()).defaultHeaders(httpHeaders -> {
httpHeaders.set("requestId", requestId);
}).build();
Mono<List> responseFlux = client.post().uri(EXTERNAL_API_PATH.get() + "/withattFluxBackPressure")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(message)).retrieve().bodyToMono(List.class);
NotificationService processing requests
#PostMapping(value = "/externalNotification/withattFluxBackPressure")
public List<NotificationResponse> sendMailMessageWAttFlux(#RequestBody List<EmailTemplate> mailMessages) throws Exception{
log.info("Processing email sending request async...");
// byte[] byteArrayResource = get file content from S3
List<NotificationResponse> response = new ArrayList<>();
Flux<NotificationResponse> responseFlux = Flux.fromIterable(mailMessages).flatMap(messages -> {
try {
return Flux.just(notificationService.sendMailWAtt(messages, byteArrayResource).map(NotificationResponse::error).orElse(NotificationResponse.success()));
} catch (IOException e) {
log.error("Exception", e);
return Flux.just(new NotificationResponse().error(e.getMessage()));
}
});
responseFlux.subscribe(new BaseSubscriber<NotificationResponse>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
log.info("called hookOnSubscribe......");
subscription.request(1);
}
#Override
protected void hookOnNext(NotificationResponse value) {
log.info("called hookOnNext.......{} ", value);
response.add(value);
request(1);
}
#Override
protected void hookOnComplete() {
log.info("called hookOnComplete.......");
}
#Override
protected void hookOnError(Throwable throwable) {
log.info("called hookOnError.......");
if(throwable instanceof ConnectException) {
log.error("called ConnectException.......");
}
if(throwable instanceof ResourceAccessException) {
log.error("called ResourceAccessException.......");
}
if(throwable instanceof ConnectTimeoutException) {
log.error("called ConnectTimeoutException.......");
}
if(throwable instanceof io.netty.channel.ConnectTimeoutException) {
log.error("called netty ConnectTimeoutException.......");
}
}
});
return response;
}```
1. When NotificationService overloads, how can it signal(backpressure) CollectorService to slow down? (Ideal scenario)
2. Alternatively, NotificationService processes 5 emails then signal/request CollectorService for the next 5.
Thanks for your time!
Following recommendations elsewhere I am attempting to parallelize my final inbound handler in a Netty pipeline as such
public final class EchoServer {
private EventLoopGroup group = new NioEventLoopGroup();
private UnorderedThreadPoolEventExecutor workers = new UnorderedThreadPoolEventExecutor(10);
public void start(int port) throws InterruptedException {
try {
Bootstrap b = new Bootstrap();
b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
#Override
protected void initChannel(NioDatagramChannel channel) throws Exception {
channel.pipeline().addLast(workers, new SimpleChannelInboundHandler<DatagramPacket>() {
#Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
System.err.println(packet);
// Simulated database delay that I have to wait to occur before repsonding
Thread.sleep(1000);
ctx.write(new DatagramPacket(Unpooled.copiedBuffer("goodbye", StandardCharsets.ISO_8859_1), packet.sender()));
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
}
});
}
});
b.bind(port).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}
}
public void stop() {
group.shutdownGracefully();
}
}
I have ten clients that connect concurrently, as a test, and I am measuring execution time for handling all the requests. As expected with the 1 second delay and sequential execution it takes just over 10 seconds. I am trying to get execution down to somewhere sub 2 seconds to prove parallel handling.
From what I understand adding the handler to the pipeline with an explicitly assigned executor is supposed to parallelize that handlers work across the thread in the executor.
Instead of seeing a increase in performance, what I am finding is that my client is not receiving the responses when I add the parallel processing. The thread sleep is there to simulate the potential time it will take to write the incoming data to a database. Am I doing something obviously wrong here?
I worked around the apparently lack of Netty support for doing final end UDP processing in parallel using standard java concurrency mechanisms.
public final class EchoServer {
private EventLoopGroup group = new NioEventLoopGroup();
private ExecutorService executors = Executors.newFixedThreadPool(10);
public void start(int port) throws InterruptedException {
try {
Bootstrap b = new Bootstrap();
b.group(group).channel(NioDatagramChannel.class).handler(new ChannelInitializer<NioDatagramChannel>() {
#Override
protected void initChannel(NioDatagramChannel channel) throws Exception {
channel.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {
#Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
CompletableFuture.runAsync(() -> {
System.err.println(packet);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("goodbye", StandardCharsets.ISO_8859_1),
packet.sender()));
}, executors);
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
}
});
}
});
b.bind(port).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}
}
public void stop() {
group.shutdownGracefully();
}
}
There appears to be very little Java 11 (pure Java non framework based) WebSocket client code examples on the web so I'm hoping StackOverflow can come to the rescue for me once again.
This is the closest I've found, but unfortunately to my (novice) eyes, it doesn't appear to be a complete solution in showing how to consume the data from the WebSocket listener.
Looking at the WebSocket.Listener implementation, the onText callback method I presume would provide what I need, but I'm struggling to figure out how to return the CompletionStage object and some sort of string data from the socket.
This is some test code I have so far.
Would appreciate assistance. Thanks
public class Main {
public static void main(String[] args) {
WebSocketClient wsc = new WebSocketClient();
wsc.startSocket("ws://demos.kaazing.com/echo");
int i = 0;
// Bad, very bad
do {} while (i == 0);
}
}
public class WebSocketClient implements WebSocket.Listener {
#Override
public void onOpen(WebSocket webSocket) {
//...
System.out.println("Go...Open".concat(
webSocket.getSubprotocol()));
}
#Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
//...
System.out.println(data.toString());
// How do I return the CompletionStage object
// return CompletionStage<String>
}
#Override
public void onError(WebSocket webSocket, Throwable error) {
//..
System.out.println("Bad day! ".concat(webSocket.toString()));
}
void startSocket(String connection) {
CompletableFuture<WebSocket> server_cf = HttpClient.
newHttpClient().
newWebSocketBuilder().
buildAsync(URI.create(connection),
new WebSocketClient());
WebSocket server = server_cf.join();
server.sendText("Hello!", true);
}
}
Below you find a working example. I have made some changes to your code above:
onOpen needs to invoke request(1) on the websocket (invoking the default implementation) in order to receive further invocations.
moved method startSocket into the main method
replaced busy waiting with a count down latch
declared class WebSocketClient as a (static) inner class
but beyond these (cosmetic) changes the program follows your idea, i.e. first a websocket connection is build and after successful construction the text Hello! is sent to the echo server. This could also be done in method onOpen directly.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
WebSocket ws = HttpClient
.newHttpClient()
.newWebSocketBuilder()
.buildAsync(URI.create("ws://demos.kaazing.com/echo"), new WebSocketClient(latch))
.join();
ws.sendText("Hello!", true);
latch.await();
}
private static class WebSocketClient implements WebSocket.Listener {
private final CountDownLatch latch;
public WebSocketClient(CountDownLatch latch) { this.latch = latch; }
#Override
public void onOpen(WebSocket webSocket) {
System.out.println("onOpen using subprotocol " + webSocket.getSubprotocol());
WebSocket.Listener.super.onOpen(webSocket);
}
#Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
System.out.println("onText received " + data);
latch.countDown();
return WebSocket.Listener.super.onText(webSocket, data, last);
}
#Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("Bad day! " + webSocket.toString());
WebSocket.Listener.super.onError(webSocket, error);
}
}
}
Btw, no supprotocol was negotiated, therefore method webSocket.getSubprotocol() returns an empty string. The output in the console is
onOpen using subprotocol
onText received Hello!
The pattern for managing a WebSocket response returning a CompletionStage is:
#Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
// return inmmediately but response is geenrated lazyly.
return CompletableFuture.supplyAsync(() -> {
String response = "Received ...";
// do slow task. Access to database or access to a server.
return response;
});
}
This simple implementation only is recommended when the response is generated quickly.
#Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
// fast response.
String response = "The text has " + data.length() + " chars";
return CompletableFuture.completedFuture(response);
}
I have had some trouble getting various examples working. Specifically, I had trouble finding examples that actually showed how to open, send, and receive simple text messages. One important piece was having a server to which to connect. Here is what I managed to make work.
package webSockets;
import java.io.IOException;
import java.net.URI;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
public class SimpleWebsocketClient extends Endpoint {
private Session session;
public SimpleWebsocketClient() {}
public SimpleWebsocketClient(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#Override
public void onClose(Session session, CloseReason reason){
System.out.println("Disconnected as a result of "+ reason.getReasonPhrase());
}
#Override
public void onError(Session session, Throwable error){
System.out.println("Error communicating with server: " + error.getMessage());
}
#Override
public void onOpen(Session s, EndpointConfig config) {
System.out.println("Session opened");
session = s;
session.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String msg) {
System.out.println("Text Message Received:" + msg);
}
});
try {
session.getBasicRemote().sendText("Hello there.");
session.getBasicRemote().sendText("Hope you are well!");
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public static void main(String...arg) {
URI uri = URI.create("ws://connect.websocket.in/v3/1?api_key=oCdCMcMPQpbvNjUIzqtvF1d2X2okWpDQj4AwARJuAgtjhzKxVEjQU6IdCjwm¬ify_self");
new SimpleWebsocketClient(uri);
while(true) {}
}
}
I want to write Junit UT case for my websocket serverendpoint code using embedded Jetty.
i tried things explained in below link:
JUnit test with javax.websocket on embedded Jetty throws RejectedExecutionException: NonBlockingThread
I want to test my onMessage callback for websocket.
If i dont use server.join() method then the connection closes as soon as it opens.
If i use server.join() method nothing happens after joining.
Below is My code.
Server startup code::
public class EmbeddedJettyServer {
private final int port;
private Server server;
public EmbeddedJettyServer(int port) {
this.port = port;
}
public void start() throws Exception {
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
// Setup the basic application "context" for this application at "/"
// This is also known as the handler tree (in jetty speak)
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
try {
// Initialize javax.websocket layer
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context);
// Add WebSocket endpoint to javax.websocket layer
wscontainer.addEndpoint(WebSocketServer.class);
System.out.println("Begin start");
server.start();
server.dump(System.err);
server.join();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
public void stop() throws Exception {
server.stop();
LOGGER.info("Jetty server stopped");
}
public URI getWebsocketUri(Class<WebSocketServer> class1) {
return server.getURI();
}
}
Client Code:
#ClientEndpoint()
public class WebSocketClientJetty {
WebSocketContainer container;
public Session connect(URI uri) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try {
// Attempt Connect
Session session = container.connectToServer(WebSocketClientJetty.class,uri);
// return container.connectToServer(WebSocketClientJetty.class, uri);
session.getBasicRemote().sendText("Hello");
// Close session
// session.close();
return session;
} finally {
}
}
public void stop() throws Exception{
if (container instanceof LifeCycle) {
((LifeCycle) container).stop();
}
}
#OnOpen
public void onWebSocketConnect(Session sess)
{
System.out.println("Socket Connected: " + sess);
}
#OnMessage
public void onWebSocketText(String message)
{
System.out.println("Received TEXT message: " + message);
}
#OnClose
public void onWebSocketClose(CloseReason reason)
{
System.out.println("Socket Closed: " + reason);
}
#OnError
public void onWebSocketError(Throwable cause)
{
cause.printStackTrace(System.err);
}
}
Serverendpoint code:
#ServerEndpoint(value = "/echo",
encoders={JsonEncoder.class})
public class WebSocketServer {
private static final Logger LOGGER =
#OnOpen
public void onOpen(Session session){
System.out.println("onopen");
some code....
}
#OnMessage
public void onMessage(String message, Session session) throws IOException{
System.out.println("onmessage");
....
}
#OnClose
public void onClose(Session session){
System.out.println("onClose");
...
}
}
Ut case:
public class WebSocketJettyTest {
private static EmbeddedJettyServer server;
#ClassRule
public static final ExternalResource integrationServer = new ExternalResource() {
#Override
protected void before() throws Throwable {
System.out.println("Starting...");
server = new EmbeddedJettyServer(8080);
server.start();
System.out.println("Started");
}
};
#Before
public void setUp() throws Exception {
}
#After
public void shutdown() throws Exception {
server.stop();
}
#Test
public void testSocket() throws Exception {
/*URI uri = server.getWebsocketUri(WebSocketServer.class);*/
URI uri = URI.create("ws://localhost:8080/echo");
WebSocketClientJetty client = new WebSocketClientJetty();
Session session = client.connect(uri);
session.getBasicRemote().sendText("hello");
Thread.sleep(6000);
client.stop();
}
}
Drop the call to
server.join();
That just makes the current thread wait until the server thread stops.
Which is making it difficult for you.
I have a Sample WebSocket Program whown below which works fine
When ever the user closes the browser or if there is any excetion Or any disconnect , the onClose Method is
being called
My question is that , Is it possible to know from the program what is the reason for onClose being called ??
Please share your views , Thanks for reading .
public class Html5Servlet extends WebSocketServlet {
private AtomicInteger index = new AtomicInteger();
private static final List<String> tickers = new ArrayList<String>();
static{
tickers.add("ajeesh");
tickers.add("peeyu");
tickers.add("kidillan");
tickers.add("entammo");
}
/**
*
*/
private static final long serialVersionUID = 1L;
public WebSocket doWebSocketConnect(HttpServletRequest req, String resp) {
//System.out.println("doWebSocketConnect");
return new StockTickerSocket();
}
protected String getMyJsonTicker() throws Exception{
return "";
}
public class StockTickerSocket implements WebSocket.OnTextMessage{
private Connection connection;
private Timer timer;
#Override
public void onClose(int arg0, String arg1) {
System.out.println("onClose called!"+arg0);
}
#Override
public void onOpen(Connection connection) {
//System.out.println("onOpen");
this.connection=connection;
this.timer=new Timer();
}
#Override
public void onMessage(String data) {
//System.out.println("onMessage");
if(data.indexOf("disconnect")>=0){
connection.close();
timer.cancel();
}else{
sendMessage();
}
}
public void disconnect() {
System.out.println("disconnect called");
}
public void onDisconnect()
{
System.out.println("onDisconnect called");
}
private void sendMessage() {
if(connection==null||!connection.isOpen()){
//System.out.println("Connection is closed!!");
return;
}
timer.schedule(new TimerTask() {
#Override
public void run() {
try{
//System.out.println("Running task");
connection.sendMessage(getMyJsonTicker());
}
catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, new Date(),5000);
}
}
}
The signature for onClose is the following ...
#Override
public void onClose(int closeCode, String closeReason) {
System.out.println("onClose called - statusCode = " + closeCode);
System.out.println(" reason = " + closeReason);
}
Where int closeCode is any of the registered Close Status Codes.
And String closeReason is an optional (per protocol spec) close reason message.