SlideShare a Scribd company logo
1 of 140
Download to read offline
Ý 
Servlet 2.2
JSP 1.1
Servlet 2.3
JSP 1.2
JSTL 1.0
Servlet 2.4
JSP 2.0
JSTL 1.1
Servlet 2.5
JSP 2.1
EL 2.1
JSTL 1.2
Servlet 3.0
JSP 2.2
EL 2.2
JSTL 1.2
Servlet 3.1
JSP 2.3
EL 3.0
JSTL 1.2
Ý


Ý
GET /hello?name=arwan HTTP/1.1
<html> … </html>
Tomcat
Undertow
Jetty
HttpServletRequest

HttpServletResponse
@WebServlet(urlPatterns = {"/hello"})
class HelloServlet extends HttpServlet { … }
Ý
Ý
Ý
Ý
Ý
Ý
Ý
Ý{
“content”: “…”
}
Ý
var es = new EventSource(‘/notification/stream');
es.onmessage = function (event) {
//
};
es.addEventListener(‘feed-notify', function(event) {
// ‘feed-notify'
console.log(event.data);
}, false);
es.onerror = function (event) {
//
};
@WebServlet("/notification/stream")

public class NotificationStreamServlet extends HttpServlet {

final static Log log = LogFactory.getLog(NotificationStreamServlet.class);


@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
log.info("in notification/stream");



response.setCharacterEncoding("utf-8");

response.setContentType("text/event-stream");



try {

NotificationStream notificationStream = new NotificationStream(obtainUsername(request));

Iterator<Notification> notifies = notificationStream.feedNotifies();



while (notifies.hasNext()) {

Notification notification = notifies.next();



ServletOutputStream outputStream = response.getOutputStream();

outputStream.write(("event: " + notification.getEvent() + "n").getBytes());

outputStream.write(("data: " + notification.getData() + "nn").getBytes());

outputStream.flush();

}

} catch (Exception error) {

log.error("error notification/stream : " + error.getMessage());

}



log.info("out notification/stream”);
}



String obtainUsername(HttpServletRequest request) {

return request.getParameter("username");

}

}
class FeedService {



final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";

final ObjectMapper MAPPER = new ObjectMapper();



FeedNotify getFeedNotify(String username) {

try {

URL url = new URL(String.format(FEED_NOTIFY_URL, username));



HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

urlConnection.setRequestMethod("GET");

urlConnection.setRequestProperty("Accept", "application/json");

urlConnection.setConnectTimeout(3000);

urlConnection.setReadTimeout(3000);



return MAPPER.readValue(urlConnection.getInputStream(), FeedNotify.class);

} catch (IOException error) {

throw new ServiceOperationException(error);

}

}



}
// FeedService , 

FeedService feedService = new FeedService();



String username = "guest";

Iterator<Notification> feedNotifies = Stream.generate(() -> feedService.getFeedNotify(username))

.map(Notification::of)

.iterator();





while (feedNotifies.hasNext()) {

Notification next = feedNotifies.next();



System.out.println(next);

}
Ý
@WebServlet(urlPatterns = "/async", asyncSupported = true)

public class SimpleAsyncServlet extends HttpServlet {

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {


// 

AsyncContext asyncContext = request.startAsync(request, response);

// 

asyncContext.setTimeout(60 * 1000);


// 

asyncContext.addListener(new AsyncListener() {

//
public void onComplete(AsyncEvent event) throws IOException { … }
// AsyncContext.setTimeout() 

public void onTimeout(AsyncEvent event) throws IOException { … }

//
public void onError(AsyncEvent event) throws IOException { … }
// 

public void onStartAsync(AsyncEvent event) throws IOException { … }

});

// 

asyncContext.start(new Runnable() {

public void run() {

// 

asyncContext.complete(); // 

}

});

}

}
@WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)

public class AsyncNotificationStreamServlet extends HttpServlet {



@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

log.info("in notification/stream/async");



response.setCharacterEncoding("utf-8");

response.setContentType("text/event-stream");



AsyncContext asyncContext = request.startAsync();

asyncContext.setTimeout(30000);

asyncContext.addListener(new AsyncListener() {

public void onComplete(AsyncEvent event) throws IOException { … }

public void onTimeout(AsyncEvent event) throws IOException { … }

public void onError(AsyncEvent event) throws IOException { … }

public void onStartAsync(AsyncEvent event) throws IOException { … }

});

asyncContext.start(() -> {

try {

NotificationStream notificationStream = new NotificationStream(obtainUsername(request));

Iterator<Notification> notifies = notificationStream.feedNotifies();



while (notifies.hasNext() && !asyncDone.get()) {

Notification notification = notifies.next();



ServletOutputStream outputStream = asyncContext.getResponse().getOutputStream();

outputStream.write(("event: " + notification.getEvent() + "n").getBytes());

outputStream.write(("data: " + notification.getData() + "nn").getBytes());

outputStream.flush();

}

} catch (Exception error) {

log.error("error notification/stream/async - " + error.getMessage());

} finally {

asyncContext.complete();

}

});



log.info("out notification/stream/async");

}
}
Ý
Ý
Ý
Ý
class NotifyApi {



static Log LOG = LogFactory.getLog(NotifyApi.class);



final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";

final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";



final ObjectMapper MAPPER = new ObjectMapper();



FeedNotify getFeedNotify(String username) {

LOG.info("FeedNotify .");



try {

URL url = new URL(String.format(FEED_NOTIFY_URL, username));

HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

FeedNotify feedNotify = MAPPER.readValue(urlConnection.getInputStream(), FeedNotify.class);



LOG.info("FeedNotify .");



return feedNotify;

} catch (IOException error) {

throw new ServiceOperationException(error);

}

}



FriendRecommendationNotify getFriendRecommendationNotify(String username) {

LOG.info("FriendRecommendationNotify .");

try {

URL url = new URL(String.format(FRIEND_NOTIFY_URL, username));

// 



LOG.info("FriendRecommendationNotify .");



return notify;

} catch (IOException error) {

throw new ServiceOperationException(error);

}

}

}
public class SynchronousCallExample {



public static void main(String[] args) {





NotifyApi notifyApi = new NotifyApi();

String username = "guest";





FeedNotify feedNotify = notifyApi.getFeedNotify(username);



// feedNotify 





FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);



// friendNotify 



}



}
FeedNotify
getFeedNotify(username)
HTTP /
FriendRecommendationNotify
getFriendRecommendationNotify(username)
HTTP /
public class AsynchronousCallByThreadExample {



static Log LOG = LogFactory.getLog(AsynchronousCallByThreadExample.class);



public static void main(String[] args) throws Exception {



NotifyApi notifyApi = new NotifyApi();

String username = "guest";



Thread feedThread = new Thread(new Runnable() {



@Override

public void run() {



FeedNotify feedNotify = notifyApi.getFeedNotify(username);

LOG.info(feedNotify);



}



});

feedThread.start();





Thread friendThread = new Thread(() -> {



FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);

LOG.info(friendNotify);



});

friendThread.start();



}



}
<<Interface>>
Executor
<<Interface>>
ExecutorService
<<Interface>>
ScheduledExecutorService
ForkJoinPool
AbstractExecutorService
ThreadPoolExecutor
ScheduledThreadPoolExecutor
ExecutorService executorService = Executors.newFixedThreadPool(4);
public class AsynchronousCallByExecutorExample {



static Log LOG = LogFactory.getLog(AsynchronousCallByExecutorExample.class);



public static void main(String[] args) throws Exception {



NotifyApi notifyApi = new NotifyApi();

String username = "guest";





Executor executor = Executors.newFixedThreadPool(4);





executor.execute(new Runnable() {


@Override

public void run() {

FeedNotify feedNotify = notifyApi.getFeedNotify(username);

LOG.info(feedNotify);

}


});



executor.execute(() -> {


FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);

LOG.info(friendNotify);


});



}



}
ExecutorService executorService = Executors.newCachedThreadPool();



Future<String> future = executorService.submit(new Callable<String>() {


@Override

public String call() throws Exception {



// 



return "asynchronous call";

}


});



String result = future.get(1, TimeUnit.SECONDS);
class NotifyApi {



static Log LOG = LogFactory.getLog(NotifyApi.class);



final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";

final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";



final ExecutorService executorService = Executors.newCachedThreadPool();

final ObjectMapper objectMapper = new ObjectMapper();



FeedNotify getFeedNotify(String username) { … }



Future<FeedNotify> getFeedNotifyForFuture(String username) {


return executorService.submit(new Callable<FeedNotify>() {


@Override

public FeedNotify call() throws Exception {

return getFeedNotify(username);

}


});

}



FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }



Future<FriendRecommendationNotify> getFriendRecommendationNotifyForFuture(String username) {

return executorService.submit(() -> getFriendRecommendationNotify(username));

}



}
NotifyApi notifyApi = new NotifyApi();

String username = "guest";





Future<FeedNotify> feedFuture = notifyApi.getFeedNotifyForFuture(username);

Future<FriendRecommendationNotify> friendFuture = notifyApi.getFriendRecommendationNotifyForFuture(username);



for (;;) {

if (feedFuture.isDone()) {

FeedNotify feedNotify = feedFuture.get();



// feedNotify 



break;

}



// 

// feedFuture.cancel(true);


LOG.info("FeedNotify .");

Thread.sleep(100);

}





FriendRecommendationNotify friendNotify = friendFuture.get(1, TimeUnit.SECONDS);



// friendNotify
getFeedNotify(username)
HTTP /
feedFuture
HTTP /
friendFuture
getFriendRecommendationNotify(username)
feedFuture.isDone() or cancel()
feedFuture.get()
friendFuture.get()
NotifyApi notifyApi = new NotifyApi();

String username = "elton";





Future<User> userFuture = notifyApi.getUserForFuture(username);

for (;;) {

if (userFuture.isDone()) {

User user = userFuture.get();



FeedNotify feedNotify = notifyApi.getFeedNotifyForFuture(user)
.get(1, TimeUnit.SECONDS);



// 



break;

}



LOG.info("User .");

Thread.sleep(100);

}
NotifyApi notifyApi = new NotifyApi();

String username = "guest";
notifyApi.getFeedNotify(username, new CompletionHandler<FeedNotify>() {



@Override

public void onSuccess(FeedNotify result) {

// 

}



@Override

public void onFailure(Throwable ex) {

// 

}


});
class NotifyApi {

// 

interface CompletionHandler<R> extends SuccessCallback<R>, FailureCallback {
}
// 

interface SuccessCallback<R> {


void onSuccess(R result);


}
// 

interface FailureCallback {


void onFailure(Throwable ex);


}


}
class NotifyApi {



static Log LOG = LogFactory.getLog(NotifyApi.class);



final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";

final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";



final ExecutorService executorService = Executors.newCachedThreadPool();

final ObjectMapper objectMapper = new ObjectMapper();



FeedNotify getFeedNotify(String username) { … }



void getFeedNotify(String username, CompletionHandler<FeedNotify> completionHandler) {

executorService.execute(new Runnable() {


@Override

public void run() {

try {

completionHandler.onSuccess(getFeedNotify(username));

} catch (Exception error) {

completionHandler.onFailure(error);

}

}


});

}



FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }



void getFriendRecommendationNotify(String username, CompletionHandler<FriendRecommendationNotify> handler) { … }



}
NotifyApi notifyApi = new NotifyApi();

String username = "guest";





notifyApi.getFeedNotify(username, new CompletionHandler<FeedNotify>() {



@Override

public void onSuccess(FeedNotify result) {

// 

}



@Override

public void onFailure(Throwable ex) {

// 

}


});





notifyApi.getFriendRecommendationNotify(username, new CompletionHandler<FriendRecommendationNotify>() {


@Override

public void onSuccess(FriendRecommendationNotify result) {

}


@Override

public void onFailure(Throwable ex) {

}


});


execute callback
getFeedNotify(username)
HTTP /
execute callback
getFriendRecommendationNotify(username)
HTTP /
NotifyApi notifyApi = new NotifyApi();

String username = "elton";





notifyApi.getUser(username, new NotifyApi.CompletionHandler<User>() {



@Override

public void onSuccess(User user) {



notifyApi.getFeedNotify(user, new NotifyApi.CompletionHandler<FeedNotify>() {



@Override

public void onSuccess(FeedNotify feedNotify) {

// 

}



@Override

public void onFailure(Throwable error) {

// 

}



});



}



@Override

public void onFailure(Throwable error) {

// 

}



});
CompletableFuture.supplyAsync(() -> {



// 



return "async task";

}).thenApply(result -> {



// 



return result.length();

}).exceptionally(error -> {



// 



return Integer.MIN_VALUE;

}).thenAccept(length -> {



// 



LOG.info("Length : " + length);

});
class NotifyApi {



static Log LOG = LogFactory.getLog(NotifyApi.class);



final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";

final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";



final ExecutorService executorService = Executors.newCachedThreadPool();

final ObjectMapper objectMapper = new ObjectMapper();



FeedNotify getFeedNotify(String username) { … }



CompletableFuture<FeedNotify> getFeedNotifyForCF(String username) {
return CompletableFuture.supplyAsync(new Supplier<FeedNotify>() {


@Override

public FeedNotify get() {

return getFeedNotify(username);

}


}, executorService);

}



FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }



CompletableFuture<FriendRecommendationNotify> getFriendRecommendationNotifyForCF(String username) {

return CompletableFuture.supplyAsync(() -> getFriendRecommendationNotify(username), executorService);

}



}
NotifyApi notifyApi = new NotifyApi();

String username = "guest";





notifyApi.getFeedNotifyForCF(username).thenAccept(feedNotify -> {

// feedNotify 

});



notifyApi.getFriendRecommendationNotifyForCF(username).thenAccept(friendNotify -> {

// friendNotify 

});





// 2 

notifyApi.getUserForCF(username)

.thenCompose(notifyApi::getFeedNotifyForCF)

.thenAccept(notifications -> {

// 

});


class NotificationStreamObservable {



ExecutorService executorService = Executors.newFixedThreadPool(1);

Future<?> future = new FutureTask<>(() -> {}, null);



NotifyApi notifyApi = new NotifyApi();



String username;

List<NotificationStreamObserver> observers = new CopyOnWriteArrayList<>();



NotificationStreamObservable(String username) {

this.username = username;

}



void register(NotificationStreamObserver observer) {

observers.add(observer);

}



void unregister(NotificationStreamObserver observer) {

observers.remove(observer);

}



void subscribe() {

future = executorService.submit(() -> {

boolean running = true;

while (running) {

Notification feedNotify = Notification.of(notifyApi.getFeedNotify(username));

observers.forEach(observer -> observer.onNotification(feedNotify));
// 

}

});

}



void unsubscribe() {

future.cancel(true);

observers.clear();

}

}
interface NotificationStreamObserver {



void onNotification(Notification notification);



}


String username = "guest";



NotificationStreamObservable observable = new NotificationStreamObservable(username);

observable.register(notification -> {



// 



});

observable.subscribe();





// , 

// observable.unsubscribe();
@WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)

public class AsyncNotificationStreamServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

log.info("in notification/stream/async");



response.setCharacterEncoding("utf-8");

response.setContentType("text/event-stream");



AtomicBoolean asyncDone = new AtomicBoolean(false);



AsyncContext asyncContext = request.startAsync();

asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);

asyncContext.addListener(new AsyncListener() {



@Override

public void onComplete(AsyncEvent event) throws IOException { }



@Override

public void onTimeout(AsyncEvent event) throws IOException { }



@Override

public void onError(AsyncEvent event) throws IOException { }



@Override

public void onStartAsync(AsyncEvent event) throws IOException { }



});


asyncContext.start(() -> {

//


});



log.info("out notification/stream/async");

}
}
@WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)

public class AsyncNotificationStreamServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

log.info("in notification/stream/async");



response.setCharacterEncoding("utf-8");

response.setContentType("text/event-stream");



AtomicBoolean asyncDone = new AtomicBoolean(false);



AsyncContext asyncContext = request.startAsync();

asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);

asyncContext.addListener(new AsyncListener() {



@Override

public void onComplete(AsyncEvent event) throws IOException { }



@Override

public void onTimeout(AsyncEvent event) throws IOException { }



@Override

public void onError(AsyncEvent event) throws IOException { }



@Override

public void onStartAsync(AsyncEvent event) throws IOException { }



});


asyncContext.start(() -> {

//


});



log.info("out notification/stream/async");

}
}
Ý
Ý
public class NotificationStreamObservable extends Observable {



final static ExecutorService executorService = Executors.newCachedThreadPool();



Iterator<Notification> feedNotifies;

Future<?> feedFuture;



public NotificationStreamObservable(NotificationStream stream) {

this.feedNotifies = Objects.requireNonNull(stream.feedNotifies());

}



public void subscribe() {

feedFuture = executorService.submit(() -> {

boolean running = true;

while (running) {

if (countObservers() > 0) {

try {

Notification notification = feedNotifies.next();



setChanged();

notifyObservers(notification);

} catch (Exception error) {

running = false;



setChanged();

notifyObservers(error);

}

}

if (Thread.interrupted()) {

running = false;

}

Thread.yield();

}

});

}



public void unsubscribe() {

feedFuture.cancel(true);

deleteObservers();

}
}
class NotificationStreamObserver implements Observer, AsyncListener {



final AsyncContext asyncContext;



public NotificationStreamObserver(AsyncContext asyncContext) {

this.asyncContext = Objects.requireNonNull(asyncContext);

}



@Override

public void update(Observable observable, Object event) {

if (event instanceof Notification) {

handler((Notification) event);

}



// 

if (event instanceof Throwable) {

handlerError(observable, (Throwable) event);

}

}



@Override

public void onComplete(AsyncEvent event) throws IOException {

log.info("complete notification/stream/async-observer");

}



@Override

public void onTimeout(AsyncEvent event) throws IOException {

handlerError(new TimeoutException("timeout"));

}



@Override

public void onError(AsyncEvent event) throws IOException {

handlerError(event.getThrowable());

}



@Override

public void onStartAsync(AsyncEvent event) throws IOException { }

// handle, handleError
}
@WebServlet(urlPatterns = "/notification/stream/observer", asyncSupported = true)

public class ObserverNotificationStreamServlet extends HttpServlet {



@Override

protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {

log.info("in notification/stream/observer");



response.setCharacterEncoding("utf-8");

response.setContentType("text/event-stream");





AsyncContext asyncContext = request.startAsync(request, response);

asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);



NotificationStream notificationStream = new NotificationStream(obtainUsername(request));

NotificationStreamObservable streamObservable = new NotificationStreamObservable(notificationStream);



NotificationStreamObserver streamObserver = new NotificationStreamObserver(asyncContext);

streamObservable.addObserver(streamObserver);

asyncContext.addListener(streamObserver);



streamObservable.subscribe();



log.info("out notification/stream/observer");

}



String obtainUsername(HttpServletRequest request) {

String username = request.getParameter("username");

if (StringUtils.hasText(username)) {

return username;

}



return "anonymous";

}


}
Ý
Ý
Ý
Ý
public class NotificationStreamObservable extends Observable {



final static ExecutorService executorService = Executors.newCachedThreadPool();



Iterator<Notification> feedNotifies;

Future<?> feedFuture;



public NotificationStreamObservable(NotificationStream stream) {

this.feedNotifies = requireNonNull(stream).feedNotifies();

}



public void subscribe() {

feedFuture = executorService.submit(() -> {

boolean running = true;

while (running) {

if (countObservers() > 0) {

try {

Notification notification = feedNotifies.next();


setChanged();

notifyObservers(notification);

} catch (Exception error) {

running = false;



setChanged();

notifyObservers(error);

}

}
// 

}

});

}

//
}
public class NotificationStreamObservable extends Observable {



final static ExecutorService executorService = Executors.newCachedThreadPool();



Iterator<Notification> feedNotifies;

Future<?> feedFuture;
Iterator<Notification> friendNotifies;

Future<?> friendFuture;



public NotificationStreamObservable(NotificationStream stream) {

this.feedNotifies = requireNonNull(stream).feedNotifies();

this.friendNotifies = requireNonNull(stream).friendRecommendationNotifies();

}



public void subscribe() {

feedFuture = executorService.submit(() -> {

boolean running = true;

while (running) {

if (countObservers() > 0) {

try {

Notification feedNotify = feedNotifies.next();

setChanged();

notifyObservers(feedNotify);
Notification friendNotify = friendNotifies.next();

setChanged();

notifyObservers(friendNotify);

} catch (Exception error) {

running = false;



setChanged();

notifyObservers(error);

}

}
// 

}

});

}

//
}
feedNotifies.next()
friendNotifies.next()
feedNotify
friendNotify
class NotificationPublisher implements Runnable {



final Iterator<Notification> notifies;

final AtomicBoolean running = new AtomicBoolean(true);



NotificationPublisher(Iterator<Notification> notifies) {

this.notifies = notifies;

}



@Override

public void run() {

while (running.get()) {

if (countObservers() > 0) {

try {

Notification notification = notifies.next();



setChanged();

notifyObservers(notification);

} catch (Exception error) {

cancel();



setChanged();

notifyObservers(error);

}

}



if (Thread.interrupted()) {

cancel();

}



Thread.yield();

}

}



void cancel() {

running.set(false);

}



}
class MultipleNotificationStreamObservable extends Observable {



final static ExecutorService executor = Executors.newCachedThreadPool();



NotificationPublisher feedPublisher;

NotificationPublisher friendPublisher;



public MultipleNotificationStreamObservable(NotificationStream stream) {

this.feedPublisher = new NotificationPublisher(requireNonNull(stream).feedNotifies());

this.friendPublisher = new NotificationPublisher(requireNonNull(stream).friendRecommendationNotifies());

}



public void subscribe() {

executor.execute(feedPublisher);

executor.execute(friendPublisher);

}



public void unsubscribe() {

feedPublisher.cancel();

friendPublisher.cancel();



deleteObservers();

}



}
class MultipleNotificationStreamObserver implements Observer, AsyncListener {



@Override

public void update(Observable observable, Object event) {


synchronized (this) {

if (event instanceof Notification) {

handler((Notification) event);

}



// 

if (event instanceof Throwable) {

handlerError((Throwable) event);

}

}


}



//
}
class MultipleNotificationStreamObserver implements Observer, AsyncListener {



ReentrantLock reentrantLock = new ReentrantLock();



@Override

public void update(Observable observable, Object event) {



reentrantLock.lock();



if (event instanceof Notification) {

handler((Notification) event);

}



// 

if (event instanceof Throwable) {

handlerError((Throwable) event);

}



reentrantLock.unlock();


}



//
}
BlockingQueue<Object> notifyQueue = new LinkedBlockingQueue<>();
class SequentialNotifyObserversPublisher implements Runnable {



final Iterator<Notification> notifies;

final AtomicBoolean running = new AtomicBoolean(true);



SequentialNotifyObserversRunnable(Iterator<Notification> notifies) {

this.notifies = notifies;

}



@Override

public void run() {

while (running.get()) {

if (countObservers() > 0) {

try {

notifyQueue.put(notifies.next());

} catch (Exception error) {

cancel();



try {

notifyQueue.put(error);

} catch (InterruptedException ignore) { }

}

}



if (Thread.interrupted()) {

cancel();

}



Thread.yield();

}

}



void cancel() {

running.set(false);

}



}
class MultipleNotificationStreamObservable extends Observable {



final static ExecutorService executor = Executors.newFixedThreadPool(3);



BlockingQueue<Object> notifyQueue = new LinkedBlockingQueue<>();

Future<?> notifyFuture;



SequentialNotifyObserversPublisher sequentialFeed;

SequentialNotifyObserversPublisher sequentialFriend;



public MultipleNotificationStreamObservable(NotificationStream stream) {

this.sequentialFeed = new SequentialNotifyObserversRunnable(stream.feedNotifies());

this.sequentialFriend = new SequentialNotifyObserversRunnable(stream.friendRecommendationNotifies());

}



public void subscribe() {

executor.execute(sequentialFeed);

executor.execute(sequentialFriend);



notifyFuture = executor.submit(() -> {

boolean running = true;

while (running) {

if (countObservers() > 0) {

try {

Object event = notifyQueue.take();



setChanged();

notifyObservers(event);

} catch (InterruptedException e) {

running = false;

}

}

if (Thread.interrupted()) {

running = false;

}

Thread.yield();

}

});

}

// 

}
void printUserInfo(String username) {

NotifyApi notifyApi = new NotifyApi();



NotifyApi.User user = notifyApi.getUser(username);

Long feedCount = notifyApi.getFeedCount(username);

Long friendCount = notifyApi.getFriendCount(username);



UserInfo userInfo = new UserInfo(user.getName(), feedCount, friendCount);



System.out.println("User Info");

System.out.println("name = " + userInfo.getName());

System.out.println("feedCount = " + userInfo.getFeedCount());

System.out.println("friendCount = " + userInfo.getFriendCount());

}




printUserInfo("fay"); // 1

printUserInfo("murphy"); // 2

printUserInfo("nichole"); // 3
void printUserInfo(String username) { … }
ExecutorService executorService = Executors.newFixedThreadPool(3);


executorService.execute(() -> printUserInfo("fay")); // 1

executorService.execute(() -> printUserInfo("murphy")); // 2

executorService.execute(() -> printUserInfo("nichole")); // 3
void printUserInfo(String username) { … }
ExecutorService executorService = Executors.newFixedThreadPool(3);


executorService.execute(() -> printUserInfo("fay")); // 1

executorService.execute(() -> printUserInfo("murphy")); // 2

executorService.execute(() -> printUserInfo("nichole")); // 3


executorService.execute(() -> printUserInfo("phillip")); // 4

executorService.execute(() -> printUserInfo("adrienne")); // 5

executorService.execute(() -> printUserInfo("nita")); // 6
ExecutorService executorService = Executors.newFixedThreadPool(1);


void printUserInfo(String username) {

CompletableFuture.supplyAsync(() -> notifyApi.getUser(username), executorService)

.thenCompose(user -> {

CompletableFuture<Long> feedCountCF = CompletableFuture.supplyAsync(

() -> notifyApi.getFeedCount(username), executorService);



CompletableFuture<Long> friendCountCF = CompletableFuture.supplyAsync(

() -> notifyApi.getFriendCount(username), executorService);



return feedCountCF.thenCombineAsync(friendCountCF, (feedCount, friendCount) -> {

return new UserInfo(user.getName(), feedCount, friendCount);

}, executorService);

})

.thenAccept(userInfo -> {

System.out.println("User Info");

System.out.println("name = " + userInfo.getName());

System.out.println("feedCount = " + userInfo.getFeedCount());

System.out.println("friendCount = " + userInfo.getFriendCount());

});

}



printUserInfo("fay"); // 1

printUserInfo("murphy"); // 2

printUserInfo("nichole"); // 3
ExecutorService executorService = Executors.newFixedThreadPool(3);


void printUserInfo(String username) {

//


}





printUserInfo("fay"); // 1

printUserInfo("murphy"); // 2

printUserInfo("nichole"); // 3



printUserInfo("phillip"); // 4

printUserInfo("adrienne"); // 5

printUserInfo("nita"); // 6
class NotificationPublisher implements Runnable {



Iterator<Notification> notifies;



NotifyObserversRunnable(Iterator<Notification> notifies) {

this.notifies = notifies;

}



@Override

public void run() {

boolean running = true;

while (running) {

if (countObservers() > 0) {

try {

Notification notification = notifies.next();



setChanged();

notifyObservers(notification);

} catch (Exception error) {

running = false;



setChanged();

notifyObservers(error);

}

}



if (Thread.interrupted()) {

running = false;

}



Thread.yield();

}

}



}
class NotificationPublisher implements Runnable {

final Iterator<Notification> notifies;

final AtomicBoolean running = new AtomicBoolean(true);


NotifyObserversRunnable(Iterator<Notification> notifies) {

this.notifies = notifies;

}



public void run() {

if (countObservers() > 0) {

CompletableFuture<Object> completableFuture = new CompletableFuture<>();

completableFuture.thenAcceptAsync(event -> {

if (running.get()) {

setChanged();

notifyObservers(event);

}

schedule(20);

}, notifyExecutor).exceptionally(throwable -> {

cancel();

setChanged();

notifyObservers(throwable);

return null;

});

try {

completableFuture.complete(notifies.next());

} catch (Exception error) {

completableFuture.completeExceptionally(error);

}

}

schedule(50);

}


void schedule(long millis) {

if (running.get()) {

serviceExecutor.schedule(this, millis, TimeUnit.MILLISECONDS);

}

}


void cancel() {

running.set(false);

}

}
class AsyncMultipleNotificationStreamObservable extends Observable {



final static ScheduledExecutorService serviceExecutor = Executors.newScheduledThreadPool(2);

final static ScheduledExecutorService notifyExecutor = Executors.newScheduledThreadPool(1);



NotifyObserversRunnable feedPublisher;

NotifyObserversRunnable friendPublisher;



public AsyncMultipleNotificationStreamObservable(NotificationStream stream) {

this.feedPublisher = new NotifyObserversRunnable(requireNonNull(stream).feedNotifies());

this.friendPublisher = new NotifyObserversRunnable(requireNonNull(stream).friendRecommendationNotifies());

}



public void subscribe() {

serviceExecutor.schedule(feedPublisher, 10, TimeUnit.MILLISECONDS);

serviceExecutor.schedule(friendPublisher, 10, TimeUnit.MILLISECONDS);

}



public void unsubscribe() {

feedPublisher.cancel();

friendPublisher.cancel();

}
}
SocketChannel channel = SocketChannel.open();

channel.configureBlocking(true);



Socket socket = channel.socket();

socket.connect(new InetSocketAddress("www.naver.com", 80));



BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));

PrintStream output = new PrintStream(socket.getOutputStream());



output.println("GET / HTTP/1.0");

output.println();



StringBuilder response = new StringBuilder();

String line = input.readLine();

while (Objects.nonNull(line)) {

response.append(line).append("n");

line = input.readLine();



// body 

if ("".equals(line)) {

while (Objects.nonNull(line)) {

line = input.readLine();

}

}

}



input.close();

output.close();
PollSelectorImpl
WindowsSelectorImpl
KQueueSelectorImpl
EPollSelectorImpl
Selector selector = Selector.open();



SocketChannel socketChannel = SocketChannel.open();

socketChannel.configureBlocking(false);



socketChannel.connect(new InetSocketAddress("www.naver.com", 80));

socketChannel.register(selector, SelectionKey.OP_CONNECT);



while (socketChannel.isOpen()) {

if (selector.select() > 0) {

Set<SelectionKey> selectionKeys = selector.selectedKeys();

Iterator<SelectionKey> iterator = selectionKeys.iterator();



while (iterator.hasNext()) {

SelectionKey selectionKey = iterator.next();



if (selectionKey.isConnectable()) {

SocketChannel channel = (SocketChannel) selectionKey.channel();


//


} else if (selectionKey.isWritable()) {

SocketChannel channel = (SocketChannel) selectionKey.channel();



// 



} else if (selectionKey.isReadable()) {

SocketChannel channel = (SocketChannel) selectionKey.channel();



// 



}

// 

iterator.remove();

}

}

}
AsynchronousChannelGroup asynchronousChannelGroup = AsynchronousChannelGroup.withFixedThreadPool(1);
AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open(asynchronousChannelGroup);
SocketAddress socketAddress = new InetSocketAddress(“www.naver.com”, 80);



asynchronousSocketChannel.connect(socketAddress, null, new CompletionHandler<Void, Void>() {

@Override

public void completed(Void v, Void attachment) {

//


asynchronousSocketChannel.write(writeBuffer, null, new CompletionHandler<Integer, Void>() {

@Override

public void completed(Integer length, Void attachment) {
//


asynchronousSocketChannel.read(readBuffer, null, new CompletionHandler<Integer, Void>() {

@Override

public void completed(Integer length, Void attachment) {
//
}

@Override

public void failed(Throwable error, Void attachment) {

// 

}

});

}

@Override

public void failed(Throwable error, Void attachment) {

// 

}

});

}

@Override

public void failed(Throwable exc, Void attachment) {

// 

}

});
✔ Netty(http://netty.io)
✔ gRPG(http://www.grpc.io)
✔ AsyncHttpClient(https://hc.apache.org/)
public FriendRecommendationNotify getRecommendationNotify(String username) throws ServiceOperationException {

try {

HttpGet request = new HttpGet(String.format(url, username, processing.name()));

HttpResponse response = httpClient.execute(request);

if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {

throw new ServiceOperationException();

}



return objectMapper.readValue(response.getEntity().getContent(), FriendRecommendationNotify.class);

} catch (IOException error) {

throw new ServiceOperationException(error);

}

}
public CompletableFuture<FriendRecommendationNotify> getRecommendationNotifyAsync(String username) {

CompletableFuture<FriendRecommendationNotify> completableFuture = new CompletableFuture<>();



HttpGet request = new HttpGet(String.format(url, username, processing.name()));

httpAsyncClient.execute(request, new FutureCallback<HttpResponse>() {



@Override

public void completed(HttpResponse response) {

try {

int statusCode = response.getStatusLine().getStatusCode();

InputStream content = response.getEntity().getContent();



if (statusCode != HttpStatus.SC_OK) {

completableFuture.completeExceptionally(new ServiceOperationException());

}



completableFuture.complete(objectMapper.readValue(content, FriendRecommendationNotify.class));

} catch (IOException error) {

completableFuture.completeExceptionally(new ServiceOperationException(error));

}

}



@Override

public void failed(Exception error) {

completableFuture.completeExceptionally(error);

}



@Override

public void cancelled() {

completableFuture.cancel(true);

}



});



return completableFuture;

}
@Test

public void getRecommendationNotify() throws Exception {

StopWatch stopWatch = new StopWatch("recommendationNotify");

stopWatch.start();



IntStream.rangeClosed(1, 10)

.mapToObj(value -> friendService.getRecommendationNotify("user-" + value))

.forEach(System.out::println);



stopWatch.stop();

System.out.println();

System.out.println(stopWatch.prettyPrint());

}



@Test

public void getRecommendationNotifyAsync() throws Exception {

StopWatch stopWatch = new StopWatch("recommendationNotifyAsync");

stopWatch.start();



IntStream.rangeClosed(1, 10)

.mapToObj(value -> friendService.getRecommendationNotifyAsync("user-" + value))

.collect(Collectors.toList())

.stream()

.map(CompletableFuture::join)

.forEach(System.out::println);



stopWatch.stop();

System.out.println();

System.out.println(stopWatch.prettyPrint());

}
class NotificationPublisher implements Runnable {



final Supplier<CompletableFuture<Notification>> notifies;

final AtomicBoolean running = new AtomicBoolean(true);



NotifyObserversRunnable(Supplier<CompletableFuture<Notification>> notifies) {

this.notifies = notifies;

}



@Override

public void run() {

if (countObservers() > 0) {

notifies.get().thenAcceptAsync(event -> {

if (running.get()) {

setChanged();

notifyObservers(event);

}



schedule(20);

}, notifyExecutor).exceptionally(throwable -> {

cancel();

setChanged();

notifyObservers(throwable);



return null;

});

} else {

schedule(50);

}

}



void schedule(long millis) {

if (running.get()) {

serviceExecutor.schedule(this, millis, TimeUnit.MILLISECONDS);

}

}



void cancel() {

running.set(false);

}

}
class NonBlockingAsyncMultipleNotificationStreamObservable extends Observable {



final static ScheduledExecutorService serviceExecutor = Executors.newScheduledThreadPool(1);

final static ScheduledExecutorService notifyExecutor = Executors.newScheduledThreadPool(1);



NotifyObserversRunnable feed;

NotifyObserversRunnable friend;



public NonBlockingAsyncMultipleNotificationStreamObservable(NotificationStream stream) {

requireNonNull(stream);



this.feed = new NotifyObserversRunnable(stream::feedNotifyAsync);

this.friend = new NotifyObserversRunnable(stream::friendRecommendationNotifyAsync);

}



public void subscribe() {

serviceExecutor.execute(feed);

serviceExecutor.execute(friend);

}



public void unsubscribe() {

if (nonNull(feed)) feed.cancel();

if (nonNull(friend)) friend.cancel();



deleteObservers();

}

}
class NonBlockingAsyncMultipleNotificationStreamObserver implements Observer, AsyncListener {



final NonBlockingAsyncMultipleNotificationStreamObservable streamObservable;

final AsyncContext asyncContext;



public NonBlockingAsyncMultipleNotificationStreamObserver(N…Observable streamObservable, AsyncContext asyncContext) {

this.streamObservable = Objects.requireNonNull(streamObservable);

this.asyncContext = Objects.requireNonNull(asyncContext);

}



@Override

public void update(Observable observable, Object event) {

if (event instanceof Notification) {

handler((Notification) event);

}



if (event instanceof Throwable) {

handlerError((Throwable) event);

}

}



private void handler(Notification notification) {

try {

log.info("revised notification/stream/non-blocking-async-concurrency : " + notification.getEvent());



ServletOutputStream outputStream = asyncContext.getResponse().getOutputStream();

outputStream.write(("event: " + notification.getEvent() + "n").getBytes());

outputStream.write(("data: " + notification.getData() + "nn").getBytes());

outputStream.flush();

} catch (IOException error) {

throw new DataWriteException(error);

}

}



private void handlerError(Throwable error) {

log.error("error notification/stream/non-blocking-async-concurrency : " + error.getMessage());



streamObservable.unsubscribe();

asyncContext.complete();

}

}
✔ 비봉쇄 입/출력을 위한 새로운 인터페이스
•ReadListener - 사용 가능한 데이터를 읽을 수 있는 방법
•WriteListener - 데이터 쓰기가 가능한 때를 알 수 있는 방법
✔ ServletInputStream 에 추가된 기능
•isFinished()
•isReady()
•setReadListener()
✔ ServletOutputStream 에 추가된 기능
•isReady()
•setWriterListener()
ServletInputStream servletInputStream = request.getInputStream();

servletInputStream.setReadListener(new ReadListener() {



@Override

public void onDataAvailable() throws IOException {

// 

}



@Override

public void onAllDataRead() throws IOException {

// 

}



@Override

public void onError(Throwable throwable) {

// 

}



});
ServletOutputStream servletOutputStream = response.getOutputStream();

servletOutputStream.setWriteListener(new WriteListener() {



@Override

public void onWritePossible() throws IOException {

// 

}



@Override

public void onError(Throwable throwable) {

// 

}



});
class NonBlockingAsyncMultipleNotificationStreamObserver implements Observer, AsyncListener, WriteListener {



final NonBlockingAsyncMultipleNotificationStreamObservable streamObservable;

final AsyncContext asyncContext;

final ServletOutputStream outputStream;



final AtomicInteger counter = new AtomicInteger(1);



public NonBlockingAsyncMultipleNotificationStreamObserver(N…Observable streamObservable, AsyncContext asyncContext) {

this.streamObservable = Objects.requireNonNull(streamObservable);

this.asyncContext = Objects.requireNonNull(asyncContext);

this.outputStream = asyncContext.getResponse().getOutputStream();

}

//


@Override

public void onWritePossible() throws IOException {

// ignore

}



@Override

public void onError(Throwable throwable) {

handlerError(throwable);

}



private void handler(Notification notification) {

String content = notification.toContent();



ioExecutor.schedule(() -> write(content.getBytes()), 10, TimeUnit.MILLISECONDS);

}

private void handlerError(Throwable error) {

log.error("error notification/stream/non-blocking-async-concurrency : " + error.getMessage());



streamObservable.unsubscribe();

asyncContext.complete();

}
// …
//
final static ScheduledExecutorService ioExecutor = Executors.newScheduledThreadPool(1);


private void write(byte[] data) {

if (outputStream.isReady()) {

try {

outputStream.write(data);



ioExecutor.schedule(this::flush, 10, TimeUnit.MILLISECONDS);

} catch (IOException error) {

handlerError(error);

}

} else {

ioExecutor.schedule(() -> write(data), 10, TimeUnit.MILLISECONDS);

}

}



private void flush() {

if (outputStream.isReady()) {

try {

outputStream.flush();

} catch (IOException error) {

handlerError(error);

}

} else {

ioExecutor.schedule(this::flush, 10, TimeUnit.MILLISECONDS);

}

}



}
Ý
Ý
Ý
Ý
Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing
Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing
Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing
Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing

More Related Content

What's hot

Java Servlets
Java ServletsJava Servlets
Java ServletsEmprovise
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기경원 이
 
Object Oriented with Java Programmazione Base
Object Oriented with Java Programmazione BaseObject Oriented with Java Programmazione Base
Object Oriented with Java Programmazione BaseFelice Pescatore
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first stepsRenato Primavera
 
Java servlets
Java servletsJava servlets
Java servletslopjuan
 
점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정Arawn Park
 
PHP - Introduction to Object Oriented Programming with PHP
PHP -  Introduction to  Object Oriented Programming with PHPPHP -  Introduction to  Object Oriented Programming with PHP
PHP - Introduction to Object Oriented Programming with PHPVibrant Technologies & Computers
 
Collections - Lists, Sets
Collections - Lists, Sets Collections - Lists, Sets
Collections - Lists, Sets Hitesh-Java
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate pptAneega
 
JUnit5 and TestContainers
JUnit5 and TestContainersJUnit5 and TestContainers
JUnit5 and TestContainersSunghyouk Bae
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootJosué Neis
 

What's hot (20)

Spring boot
Spring bootSpring boot
Spring boot
 
Java Servlets
Java ServletsJava Servlets
Java Servlets
 
Java exception
Java exception Java exception
Java exception
 
Servlets
ServletsServlets
Servlets
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
Object Oriented with Java Programmazione Base
Object Oriented with Java Programmazione BaseObject Oriented with Java Programmazione Base
Object Oriented with Java Programmazione Base
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first steps
 
Java servlets
Java servletsJava servlets
Java servlets
 
점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정
 
Spring Security 5
Spring Security 5Spring Security 5
Spring Security 5
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
Spring Security
Spring SecuritySpring Security
Spring Security
 
Spring Boot Tutorial
Spring Boot TutorialSpring Boot Tutorial
Spring Boot Tutorial
 
PHP - Introduction to Object Oriented Programming with PHP
PHP -  Introduction to  Object Oriented Programming with PHPPHP -  Introduction to  Object Oriented Programming with PHP
PHP - Introduction to Object Oriented Programming with PHP
 
Collections - Lists, Sets
Collections - Lists, Sets Collections - Lists, Sets
Collections - Lists, Sets
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate ppt
 
JUnit5 and TestContainers
JUnit5 and TestContainersJUnit5 and TestContainers
JUnit5 and TestContainers
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
 
JPA Best Practices
JPA Best PracticesJPA Best Practices
JPA Best Practices
 

Viewers also liked

Spring framework 4.x
Spring framework 4.xSpring framework 4.x
Spring framework 4.xArawn Park
 
Tuning and development with SIP Servlets on Mobicents
Tuning and development with SIP Servlets on MobicentsTuning and development with SIP Servlets on Mobicents
Tuning and development with SIP Servlets on MobicentsJean Deruelle
 
씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 APIArawn Park
 
한글 폰트 테스트
한글 폰트 테스트한글 폰트 테스트
한글 폰트 테스트김 진수
 
Vagrant와 chef로 개발서버 구축 자동화하기
Vagrant와 chef로 개발서버 구축 자동화하기Vagrant와 chef로 개발서버 구축 자동화하기
Vagrant와 chef로 개발서버 구축 자동화하기Arawn Park
 
Java EE 8: What Servlet 4 and HTTP2 Mean
Java EE 8: What Servlet 4 and HTTP2 MeanJava EE 8: What Servlet 4 and HTTP2 Mean
Java EE 8: What Servlet 4 and HTTP2 MeanAlex Theedom
 

Viewers also liked (6)

Spring framework 4.x
Spring framework 4.xSpring framework 4.x
Spring framework 4.x
 
Tuning and development with SIP Servlets on Mobicents
Tuning and development with SIP Servlets on MobicentsTuning and development with SIP Servlets on Mobicents
Tuning and development with SIP Servlets on Mobicents
 
씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API
 
한글 폰트 테스트
한글 폰트 테스트한글 폰트 테스트
한글 폰트 테스트
 
Vagrant와 chef로 개발서버 구축 자동화하기
Vagrant와 chef로 개발서버 구축 자동화하기Vagrant와 chef로 개발서버 구축 자동화하기
Vagrant와 chef로 개발서버 구축 자동화하기
 
Java EE 8: What Servlet 4 and HTTP2 Mean
Java EE 8: What Servlet 4 and HTTP2 MeanJava EE 8: What Servlet 4 and HTTP2 Mean
Java EE 8: What Servlet 4 and HTTP2 Mean
 

Similar to Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing

Jersey framework
Jersey frameworkJersey framework
Jersey frameworkknight1128
 
swift-nio のアーキテクチャーと RxHttpClient
swift-nio のアーキテクチャーと RxHttpClientswift-nio のアーキテクチャーと RxHttpClient
swift-nio のアーキテクチャーと RxHttpClientShinya Mochida
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to NodejsGabriele Lana
 
13 networking, mobile services, and authentication
13   networking, mobile services, and authentication13   networking, mobile services, and authentication
13 networking, mobile services, and authenticationWindowsPhoneRocks
 
XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話Takehito Tanabe
 
Note Use Java Write a web server that is capable of processing only.pdf
Note Use Java Write a web server that is capable of processing only.pdfNote Use Java Write a web server that is capable of processing only.pdf
Note Use Java Write a web server that is capable of processing only.pdffatoryoutlets
 
Unit testing CourseSites Apache Filter
Unit testing CourseSites Apache FilterUnit testing CourseSites Apache Filter
Unit testing CourseSites Apache FilterWayan Wira
 
DWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A TutorialDWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A Tutorialjbarciauskas
 
Client server part 12
Client server part 12Client server part 12
Client server part 12fadlihulopi
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsYakov Fain
 
Laporan multiclient chatting client server
Laporan multiclient chatting client serverLaporan multiclient chatting client server
Laporan multiclient chatting client servertrilestari08
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranRobert Nyman
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeDaniel Wellman
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programingwahyuseptiansyah
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasyJBug Italy
 

Similar to Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing (20)

Jersey framework
Jersey frameworkJersey framework
Jersey framework
 
swift-nio のアーキテクチャーと RxHttpClient
swift-nio のアーキテクチャーと RxHttpClientswift-nio のアーキテクチャーと RxHttpClient
swift-nio のアーキテクチャーと RxHttpClient
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
 
13 networking, mobile services, and authentication
13   networking, mobile services, and authentication13   networking, mobile services, and authentication
13 networking, mobile services, and authentication
 
XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話
 
Server1
Server1Server1
Server1
 
Note Use Java Write a web server that is capable of processing only.pdf
Note Use Java Write a web server that is capable of processing only.pdfNote Use Java Write a web server that is capable of processing only.pdf
Note Use Java Write a web server that is capable of processing only.pdf
 
Unit testing CourseSites Apache Filter
Unit testing CourseSites Apache FilterUnit testing CourseSites Apache Filter
Unit testing CourseSites Apache Filter
 
DWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A TutorialDWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A Tutorial
 
Client server part 12
Client server part 12Client server part 12
Client server part 12
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSockets
 
Advancedservletsjsp
AdvancedservletsjspAdvancedservletsjsp
Advancedservletsjsp
 
Laporan multiclient chatting client server
Laporan multiclient chatting client serverLaporan multiclient chatting client server
Laporan multiclient chatting client server
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - Altran
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
Multithreading in Java
Multithreading in JavaMultithreading in Java
Multithreading in Java
 
Jason parsing
Jason parsingJason parsing
Jason parsing
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
 

More from Arawn Park

우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?Arawn Park
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
 
kotlinx.serialization
kotlinx.serializationkotlinx.serialization
kotlinx.serializationArawn Park
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기Arawn Park
 
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다Arawn Park
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정Arawn Park
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to KotlinArawn Park
 
Spring framework 3.2 > 4.0 — themes and trends
Spring framework 3.2 > 4.0 — themes and trendsSpring framework 3.2 > 4.0 — themes and trends
Spring framework 3.2 > 4.0 — themes and trendsArawn Park
 
overview of spring4
overview of spring4overview of spring4
overview of spring4Arawn Park
 
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )Arawn Park
 
Resource Handling in Spring MVC
Resource Handling in Spring MVCResource Handling in Spring MVC
Resource Handling in Spring MVCArawn Park
 
[Spring Camp 2013] Java Configuration 없인 못살아!
[Spring Camp 2013] Java Configuration 없인 못살아![Spring Camp 2013] Java Configuration 없인 못살아!
[Spring Camp 2013] Java Configuration 없인 못살아!Arawn Park
 

More from Arawn Park (12)

우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
kotlinx.serialization
kotlinx.serializationkotlinx.serialization
kotlinx.serialization
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
 
Spring framework 3.2 > 4.0 — themes and trends
Spring framework 3.2 > 4.0 — themes and trendsSpring framework 3.2 > 4.0 — themes and trends
Spring framework 3.2 > 4.0 — themes and trends
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
 
Resource Handling in Spring MVC
Resource Handling in Spring MVCResource Handling in Spring MVC
Resource Handling in Spring MVC
 
[Spring Camp 2013] Java Configuration 없인 못살아!
[Spring Camp 2013] Java Configuration 없인 못살아![Spring Camp 2013] Java Configuration 없인 못살아!
[Spring Camp 2013] Java Configuration 없인 못살아!
 

Recently uploaded

Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxRTS corp
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdfAndrey Devyatkin
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdfSteve Caron
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesKrzysztofKkol1
 

Recently uploaded (20)

Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
 

Java Web Development Guide: Servlets, JSP, JSTL, EL, Async Processing

  • 1.
  • 2.
  • 4. Servlet 2.2 JSP 1.1 Servlet 2.3 JSP 1.2 JSTL 1.0 Servlet 2.4 JSP 2.0 JSTL 1.1 Servlet 2.5 JSP 2.1 EL 2.1 JSTL 1.2 Servlet 3.0 JSP 2.2 EL 2.2 JSTL 1.2 Servlet 3.1 JSP 2.3 EL 3.0 JSTL 1.2
  • 6. Ý GET /hello?name=arwan HTTP/1.1 <html> … </html> Tomcat Undertow Jetty HttpServletRequest
 HttpServletResponse @WebServlet(urlPatterns = {"/hello"}) class HelloServlet extends HttpServlet { … }
  • 7.
  • 8.
  • 11.
  • 12. Ý
  • 13. var es = new EventSource(‘/notification/stream'); es.onmessage = function (event) { // }; es.addEventListener(‘feed-notify', function(event) { // ‘feed-notify' console.log(event.data); }, false); es.onerror = function (event) { // };
  • 14. @WebServlet("/notification/stream")
 public class NotificationStreamServlet extends HttpServlet {
 final static Log log = LogFactory.getLog(NotificationStreamServlet.class); 
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception { log.info("in notification/stream");
 
 response.setCharacterEncoding("utf-8");
 response.setContentType("text/event-stream");
 
 try {
 NotificationStream notificationStream = new NotificationStream(obtainUsername(request));
 Iterator<Notification> notifies = notificationStream.feedNotifies();
 
 while (notifies.hasNext()) {
 Notification notification = notifies.next();
 
 ServletOutputStream outputStream = response.getOutputStream();
 outputStream.write(("event: " + notification.getEvent() + "n").getBytes());
 outputStream.write(("data: " + notification.getData() + "nn").getBytes());
 outputStream.flush();
 }
 } catch (Exception error) {
 log.error("error notification/stream : " + error.getMessage());
 }
 
 log.info("out notification/stream”); }
 
 String obtainUsername(HttpServletRequest request) {
 return request.getParameter("username");
 }
 }
  • 15. class FeedService {
 
 final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";
 final ObjectMapper MAPPER = new ObjectMapper();
 
 FeedNotify getFeedNotify(String username) {
 try {
 URL url = new URL(String.format(FEED_NOTIFY_URL, username));
 
 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 urlConnection.setRequestMethod("GET");
 urlConnection.setRequestProperty("Accept", "application/json");
 urlConnection.setConnectTimeout(3000);
 urlConnection.setReadTimeout(3000);
 
 return MAPPER.readValue(urlConnection.getInputStream(), FeedNotify.class);
 } catch (IOException error) {
 throw new ServiceOperationException(error);
 }
 }
 
 } // FeedService , 
 FeedService feedService = new FeedService();
 
 String username = "guest";
 Iterator<Notification> feedNotifies = Stream.generate(() -> feedService.getFeedNotify(username))
 .map(Notification::of)
 .iterator();
 
 
 while (feedNotifies.hasNext()) {
 Notification next = feedNotifies.next();
 
 System.out.println(next);
 }
  • 16.
  • 17.
  • 18.
  • 19. Ý
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26. @WebServlet(urlPatterns = "/async", asyncSupported = true)
 public class SimpleAsyncServlet extends HttpServlet {
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception { 
 // 
 AsyncContext asyncContext = request.startAsync(request, response);
 // 
 asyncContext.setTimeout(60 * 1000); 
 // 
 asyncContext.addListener(new AsyncListener() {
 // public void onComplete(AsyncEvent event) throws IOException { … } // AsyncContext.setTimeout() 
 public void onTimeout(AsyncEvent event) throws IOException { … }
 // public void onError(AsyncEvent event) throws IOException { … } // 
 public void onStartAsync(AsyncEvent event) throws IOException { … }
 });
 // 
 asyncContext.start(new Runnable() {
 public void run() {
 // 
 asyncContext.complete(); // 
 }
 });
 }
 }
  • 27. @WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)
 public class AsyncNotificationStreamServlet extends HttpServlet {
 
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
 log.info("in notification/stream/async");
 
 response.setCharacterEncoding("utf-8");
 response.setContentType("text/event-stream");
 
 AsyncContext asyncContext = request.startAsync();
 asyncContext.setTimeout(30000);
 asyncContext.addListener(new AsyncListener() {
 public void onComplete(AsyncEvent event) throws IOException { … }
 public void onTimeout(AsyncEvent event) throws IOException { … }
 public void onError(AsyncEvent event) throws IOException { … }
 public void onStartAsync(AsyncEvent event) throws IOException { … }
 });
 asyncContext.start(() -> {
 try {
 NotificationStream notificationStream = new NotificationStream(obtainUsername(request));
 Iterator<Notification> notifies = notificationStream.feedNotifies();
 
 while (notifies.hasNext() && !asyncDone.get()) {
 Notification notification = notifies.next();
 
 ServletOutputStream outputStream = asyncContext.getResponse().getOutputStream();
 outputStream.write(("event: " + notification.getEvent() + "n").getBytes());
 outputStream.write(("data: " + notification.getData() + "nn").getBytes());
 outputStream.flush();
 }
 } catch (Exception error) {
 log.error("error notification/stream/async - " + error.getMessage());
 } finally {
 asyncContext.complete();
 }
 });
 
 log.info("out notification/stream/async");
 } }
  • 28.
  • 29.
  • 30.
  • 31.
  • 33.
  • 34.
  • 35. class NotifyApi {
 
 static Log LOG = LogFactory.getLog(NotifyApi.class);
 
 final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";
 final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";
 
 final ObjectMapper MAPPER = new ObjectMapper();
 
 FeedNotify getFeedNotify(String username) {
 LOG.info("FeedNotify .");
 
 try {
 URL url = new URL(String.format(FEED_NOTIFY_URL, username));
 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 FeedNotify feedNotify = MAPPER.readValue(urlConnection.getInputStream(), FeedNotify.class);
 
 LOG.info("FeedNotify .");
 
 return feedNotify;
 } catch (IOException error) {
 throw new ServiceOperationException(error);
 }
 }
 
 FriendRecommendationNotify getFriendRecommendationNotify(String username) {
 LOG.info("FriendRecommendationNotify .");
 try {
 URL url = new URL(String.format(FRIEND_NOTIFY_URL, username));
 // 
 
 LOG.info("FriendRecommendationNotify .");
 
 return notify;
 } catch (IOException error) {
 throw new ServiceOperationException(error);
 }
 }
 }
  • 36. public class SynchronousCallExample {
 
 public static void main(String[] args) {
 
 
 NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 
 FeedNotify feedNotify = notifyApi.getFeedNotify(username);
 
 // feedNotify 
 
 
 FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);
 
 // friendNotify 
 
 }
 
 }
  • 37.
  • 39.
  • 40. public class AsynchronousCallByThreadExample {
 
 static Log LOG = LogFactory.getLog(AsynchronousCallByThreadExample.class);
 
 public static void main(String[] args) throws Exception {
 
 NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 Thread feedThread = new Thread(new Runnable() {
 
 @Override
 public void run() {
 
 FeedNotify feedNotify = notifyApi.getFeedNotify(username);
 LOG.info(feedNotify);
 
 }
 
 });
 feedThread.start();
 
 
 Thread friendThread = new Thread(() -> {
 
 FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);
 LOG.info(friendNotify);
 
 });
 friendThread.start();
 
 }
 
 }
  • 41.
  • 42.
  • 44. public class AsynchronousCallByExecutorExample {
 
 static Log LOG = LogFactory.getLog(AsynchronousCallByExecutorExample.class);
 
 public static void main(String[] args) throws Exception {
 
 NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 
 Executor executor = Executors.newFixedThreadPool(4);
 
 
 executor.execute(new Runnable() { 
 @Override
 public void run() {
 FeedNotify feedNotify = notifyApi.getFeedNotify(username);
 LOG.info(feedNotify);
 } 
 });
 
 executor.execute(() -> { 
 FriendRecommendationNotify friendNotify = notifyApi.getFriendRecommendationNotify(username);
 LOG.info(friendNotify); 
 });
 
 }
 
 }
  • 45.
  • 46. ExecutorService executorService = Executors.newCachedThreadPool();
 
 Future<String> future = executorService.submit(new Callable<String>() { 
 @Override
 public String call() throws Exception {
 
 // 
 
 return "asynchronous call";
 } 
 });
 
 String result = future.get(1, TimeUnit.SECONDS);
  • 47. class NotifyApi {
 
 static Log LOG = LogFactory.getLog(NotifyApi.class);
 
 final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";
 final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";
 
 final ExecutorService executorService = Executors.newCachedThreadPool();
 final ObjectMapper objectMapper = new ObjectMapper();
 
 FeedNotify getFeedNotify(String username) { … }
 
 Future<FeedNotify> getFeedNotifyForFuture(String username) { 
 return executorService.submit(new Callable<FeedNotify>() { 
 @Override
 public FeedNotify call() throws Exception {
 return getFeedNotify(username);
 } 
 });
 }
 
 FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }
 
 Future<FriendRecommendationNotify> getFriendRecommendationNotifyForFuture(String username) {
 return executorService.submit(() -> getFriendRecommendationNotify(username));
 }
 
 }
  • 48. NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 
 Future<FeedNotify> feedFuture = notifyApi.getFeedNotifyForFuture(username);
 Future<FriendRecommendationNotify> friendFuture = notifyApi.getFriendRecommendationNotifyForFuture(username);
 
 for (;;) {
 if (feedFuture.isDone()) {
 FeedNotify feedNotify = feedFuture.get();
 
 // feedNotify 
 
 break;
 }
 
 // 
 // feedFuture.cancel(true); 
 LOG.info("FeedNotify .");
 Thread.sleep(100);
 }
 
 
 FriendRecommendationNotify friendNotify = friendFuture.get(1, TimeUnit.SECONDS);
 
 // friendNotify
  • 49.
  • 51. NotifyApi notifyApi = new NotifyApi();
 String username = "elton";
 
 
 Future<User> userFuture = notifyApi.getUserForFuture(username);
 for (;;) {
 if (userFuture.isDone()) {
 User user = userFuture.get();
 
 FeedNotify feedNotify = notifyApi.getFeedNotifyForFuture(user) .get(1, TimeUnit.SECONDS);
 
 // 
 
 break;
 }
 
 LOG.info("User .");
 Thread.sleep(100);
 }
  • 52. NotifyApi notifyApi = new NotifyApi();
 String username = "guest"; notifyApi.getFeedNotify(username, new CompletionHandler<FeedNotify>() {
 
 @Override
 public void onSuccess(FeedNotify result) {
 // 
 }
 
 @Override
 public void onFailure(Throwable ex) {
 // 
 } 
 });
  • 53. class NotifyApi {
 // 
 interface CompletionHandler<R> extends SuccessCallback<R>, FailureCallback { } // 
 interface SuccessCallback<R> { 
 void onSuccess(R result); 
 } // 
 interface FailureCallback { 
 void onFailure(Throwable ex); 
 } 
 }
  • 54. class NotifyApi {
 
 static Log LOG = LogFactory.getLog(NotifyApi.class);
 
 final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";
 final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";
 
 final ExecutorService executorService = Executors.newCachedThreadPool();
 final ObjectMapper objectMapper = new ObjectMapper();
 
 FeedNotify getFeedNotify(String username) { … }
 
 void getFeedNotify(String username, CompletionHandler<FeedNotify> completionHandler) {
 executorService.execute(new Runnable() { 
 @Override
 public void run() {
 try {
 completionHandler.onSuccess(getFeedNotify(username));
 } catch (Exception error) {
 completionHandler.onFailure(error);
 }
 } 
 });
 }
 
 FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }
 
 void getFriendRecommendationNotify(String username, CompletionHandler<FriendRecommendationNotify> handler) { … }
 
 }
  • 55. NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 
 notifyApi.getFeedNotify(username, new CompletionHandler<FeedNotify>() {
 
 @Override
 public void onSuccess(FeedNotify result) {
 // 
 }
 
 @Override
 public void onFailure(Throwable ex) {
 // 
 } 
 });
 
 
 notifyApi.getFriendRecommendationNotify(username, new CompletionHandler<FriendRecommendationNotify>() { 
 @Override
 public void onSuccess(FriendRecommendationNotify result) {
 } 
 @Override
 public void onFailure(Throwable ex) {
 } 
 }); 

  • 56.
  • 57. execute callback getFeedNotify(username) HTTP / execute callback getFriendRecommendationNotify(username) HTTP /
  • 58. NotifyApi notifyApi = new NotifyApi();
 String username = "elton";
 
 
 notifyApi.getUser(username, new NotifyApi.CompletionHandler<User>() {
 
 @Override
 public void onSuccess(User user) {
 
 notifyApi.getFeedNotify(user, new NotifyApi.CompletionHandler<FeedNotify>() {
 
 @Override
 public void onSuccess(FeedNotify feedNotify) {
 // 
 }
 
 @Override
 public void onFailure(Throwable error) {
 // 
 }
 
 });
 
 }
 
 @Override
 public void onFailure(Throwable error) {
 // 
 }
 
 });
  • 59. CompletableFuture.supplyAsync(() -> {
 
 // 
 
 return "async task";
 }).thenApply(result -> {
 
 // 
 
 return result.length();
 }).exceptionally(error -> {
 
 // 
 
 return Integer.MIN_VALUE;
 }).thenAccept(length -> {
 
 // 
 
 LOG.info("Length : " + length);
 });
  • 60. class NotifyApi {
 
 static Log LOG = LogFactory.getLog(NotifyApi.class);
 
 final String FEED_NOTIFY_URL = "http://localhost:9000/user/%s/feed";
 final String FRIEND_NOTIFY_URL = "http://localhost:9000/user/%s/friend-recommendation";
 
 final ExecutorService executorService = Executors.newCachedThreadPool();
 final ObjectMapper objectMapper = new ObjectMapper();
 
 FeedNotify getFeedNotify(String username) { … }
 
 CompletableFuture<FeedNotify> getFeedNotifyForCF(String username) { return CompletableFuture.supplyAsync(new Supplier<FeedNotify>() { 
 @Override
 public FeedNotify get() {
 return getFeedNotify(username);
 } 
 }, executorService);
 }
 
 FriendRecommendationNotify getFriendRecommendationNotify(String username) { … }
 
 CompletableFuture<FriendRecommendationNotify> getFriendRecommendationNotifyForCF(String username) {
 return CompletableFuture.supplyAsync(() -> getFriendRecommendationNotify(username), executorService);
 }
 
 }
  • 61. NotifyApi notifyApi = new NotifyApi();
 String username = "guest";
 
 
 notifyApi.getFeedNotifyForCF(username).thenAccept(feedNotify -> {
 // feedNotify 
 });
 
 notifyApi.getFriendRecommendationNotifyForCF(username).thenAccept(friendNotify -> {
 // friendNotify 
 });
 
 
 // 2 
 notifyApi.getUserForCF(username)
 .thenCompose(notifyApi::getFeedNotifyForCF)
 .thenAccept(notifications -> {
 // 
 });
  • 62.
  • 63.
  • 64. class NotificationStreamObservable {
 
 ExecutorService executorService = Executors.newFixedThreadPool(1);
 Future<?> future = new FutureTask<>(() -> {}, null);
 
 NotifyApi notifyApi = new NotifyApi();
 
 String username;
 List<NotificationStreamObserver> observers = new CopyOnWriteArrayList<>();
 
 NotificationStreamObservable(String username) {
 this.username = username;
 }
 
 void register(NotificationStreamObserver observer) {
 observers.add(observer);
 }
 
 void unregister(NotificationStreamObserver observer) {
 observers.remove(observer);
 }
 
 void subscribe() {
 future = executorService.submit(() -> {
 boolean running = true;
 while (running) {
 Notification feedNotify = Notification.of(notifyApi.getFeedNotify(username));
 observers.forEach(observer -> observer.onNotification(feedNotify)); // 
 }
 });
 }
 
 void unsubscribe() {
 future.cancel(true);
 observers.clear();
 }
 }
  • 65. interface NotificationStreamObserver {
 
 void onNotification(Notification notification);
 
 } 
 String username = "guest";
 
 NotificationStreamObservable observable = new NotificationStreamObservable(username);
 observable.register(notification -> {
 
 // 
 
 });
 observable.subscribe();
 
 
 // , 
 // observable.unsubscribe();
  • 66.
  • 67.
  • 68. @WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)
 public class AsyncNotificationStreamServlet extends HttpServlet {
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
 log.info("in notification/stream/async");
 
 response.setCharacterEncoding("utf-8");
 response.setContentType("text/event-stream");
 
 AtomicBoolean asyncDone = new AtomicBoolean(false);
 
 AsyncContext asyncContext = request.startAsync();
 asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);
 asyncContext.addListener(new AsyncListener() {
 
 @Override
 public void onComplete(AsyncEvent event) throws IOException { }
 
 @Override
 public void onTimeout(AsyncEvent event) throws IOException { }
 
 @Override
 public void onError(AsyncEvent event) throws IOException { }
 
 @Override
 public void onStartAsync(AsyncEvent event) throws IOException { }
 
 }); 
 asyncContext.start(() -> {
 // 
 });
 
 log.info("out notification/stream/async");
 } }
  • 69. @WebServlet(urlPatterns = "/notification/stream/async", asyncSupported = true)
 public class AsyncNotificationStreamServlet extends HttpServlet {
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
 log.info("in notification/stream/async");
 
 response.setCharacterEncoding("utf-8");
 response.setContentType("text/event-stream");
 
 AtomicBoolean asyncDone = new AtomicBoolean(false);
 
 AsyncContext asyncContext = request.startAsync();
 asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);
 asyncContext.addListener(new AsyncListener() {
 
 @Override
 public void onComplete(AsyncEvent event) throws IOException { }
 
 @Override
 public void onTimeout(AsyncEvent event) throws IOException { }
 
 @Override
 public void onError(AsyncEvent event) throws IOException { }
 
 @Override
 public void onStartAsync(AsyncEvent event) throws IOException { }
 
 }); 
 asyncContext.start(() -> {
 // 
 });
 
 log.info("out notification/stream/async");
 } }
  • 70. Ý Ý
  • 71. public class NotificationStreamObservable extends Observable {
 
 final static ExecutorService executorService = Executors.newCachedThreadPool();
 
 Iterator<Notification> feedNotifies;
 Future<?> feedFuture;
 
 public NotificationStreamObservable(NotificationStream stream) {
 this.feedNotifies = Objects.requireNonNull(stream.feedNotifies());
 }
 
 public void subscribe() {
 feedFuture = executorService.submit(() -> {
 boolean running = true;
 while (running) {
 if (countObservers() > 0) {
 try {
 Notification notification = feedNotifies.next();
 
 setChanged();
 notifyObservers(notification);
 } catch (Exception error) {
 running = false;
 
 setChanged();
 notifyObservers(error);
 }
 }
 if (Thread.interrupted()) {
 running = false;
 }
 Thread.yield();
 }
 });
 }
 
 public void unsubscribe() {
 feedFuture.cancel(true);
 deleteObservers();
 } }
  • 72. class NotificationStreamObserver implements Observer, AsyncListener {
 
 final AsyncContext asyncContext;
 
 public NotificationStreamObserver(AsyncContext asyncContext) {
 this.asyncContext = Objects.requireNonNull(asyncContext);
 }
 
 @Override
 public void update(Observable observable, Object event) {
 if (event instanceof Notification) {
 handler((Notification) event);
 }
 
 // 
 if (event instanceof Throwable) {
 handlerError(observable, (Throwable) event);
 }
 }
 
 @Override
 public void onComplete(AsyncEvent event) throws IOException {
 log.info("complete notification/stream/async-observer");
 }
 
 @Override
 public void onTimeout(AsyncEvent event) throws IOException {
 handlerError(new TimeoutException("timeout"));
 }
 
 @Override
 public void onError(AsyncEvent event) throws IOException {
 handlerError(event.getThrowable());
 }
 
 @Override
 public void onStartAsync(AsyncEvent event) throws IOException { }
 // handle, handleError }
  • 73. @WebServlet(urlPatterns = "/notification/stream/observer", asyncSupported = true)
 public class ObserverNotificationStreamServlet extends HttpServlet {
 
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response) throws Exception {
 log.info("in notification/stream/observer");
 
 response.setCharacterEncoding("utf-8");
 response.setContentType("text/event-stream");
 
 
 AsyncContext asyncContext = request.startAsync(request, response);
 asyncContext.setTimeout((new Random().nextInt(5) + 5) * 1000);
 
 NotificationStream notificationStream = new NotificationStream(obtainUsername(request));
 NotificationStreamObservable streamObservable = new NotificationStreamObservable(notificationStream);
 
 NotificationStreamObserver streamObserver = new NotificationStreamObserver(asyncContext);
 streamObservable.addObserver(streamObserver);
 asyncContext.addListener(streamObserver);
 
 streamObservable.subscribe();
 
 log.info("out notification/stream/observer");
 }
 
 String obtainUsername(HttpServletRequest request) {
 String username = request.getParameter("username");
 if (StringUtils.hasText(username)) {
 return username;
 }
 
 return "anonymous";
 } 
 }
  • 74.
  • 75.
  • 76.
  • 78. public class NotificationStreamObservable extends Observable {
 
 final static ExecutorService executorService = Executors.newCachedThreadPool();
 
 Iterator<Notification> feedNotifies;
 Future<?> feedFuture;
 
 public NotificationStreamObservable(NotificationStream stream) {
 this.feedNotifies = requireNonNull(stream).feedNotifies();
 }
 
 public void subscribe() {
 feedFuture = executorService.submit(() -> {
 boolean running = true;
 while (running) {
 if (countObservers() > 0) {
 try {
 Notification notification = feedNotifies.next(); 
 setChanged();
 notifyObservers(notification);
 } catch (Exception error) {
 running = false;
 
 setChanged();
 notifyObservers(error);
 }
 } // 
 }
 });
 }
 // }
  • 79. public class NotificationStreamObservable extends Observable {
 
 final static ExecutorService executorService = Executors.newCachedThreadPool();
 
 Iterator<Notification> feedNotifies;
 Future<?> feedFuture; Iterator<Notification> friendNotifies;
 Future<?> friendFuture;
 
 public NotificationStreamObservable(NotificationStream stream) {
 this.feedNotifies = requireNonNull(stream).feedNotifies();
 this.friendNotifies = requireNonNull(stream).friendRecommendationNotifies();
 }
 
 public void subscribe() {
 feedFuture = executorService.submit(() -> {
 boolean running = true;
 while (running) {
 if (countObservers() > 0) {
 try {
 Notification feedNotify = feedNotifies.next();
 setChanged();
 notifyObservers(feedNotify); Notification friendNotify = friendNotifies.next();
 setChanged();
 notifyObservers(friendNotify);
 } catch (Exception error) {
 running = false;
 
 setChanged();
 notifyObservers(error);
 }
 } // 
 }
 });
 }
 // }
  • 81. class NotificationPublisher implements Runnable {
 
 final Iterator<Notification> notifies;
 final AtomicBoolean running = new AtomicBoolean(true);
 
 NotificationPublisher(Iterator<Notification> notifies) {
 this.notifies = notifies;
 }
 
 @Override
 public void run() {
 while (running.get()) {
 if (countObservers() > 0) {
 try {
 Notification notification = notifies.next();
 
 setChanged();
 notifyObservers(notification);
 } catch (Exception error) {
 cancel();
 
 setChanged();
 notifyObservers(error);
 }
 }
 
 if (Thread.interrupted()) {
 cancel();
 }
 
 Thread.yield();
 }
 }
 
 void cancel() {
 running.set(false);
 }
 
 }
  • 82. class MultipleNotificationStreamObservable extends Observable {
 
 final static ExecutorService executor = Executors.newCachedThreadPool();
 
 NotificationPublisher feedPublisher;
 NotificationPublisher friendPublisher;
 
 public MultipleNotificationStreamObservable(NotificationStream stream) {
 this.feedPublisher = new NotificationPublisher(requireNonNull(stream).feedNotifies());
 this.friendPublisher = new NotificationPublisher(requireNonNull(stream).friendRecommendationNotifies());
 }
 
 public void subscribe() {
 executor.execute(feedPublisher);
 executor.execute(friendPublisher);
 }
 
 public void unsubscribe() {
 feedPublisher.cancel();
 friendPublisher.cancel();
 
 deleteObservers();
 }
 
 }
  • 83.
  • 84.
  • 85.
  • 86. class MultipleNotificationStreamObserver implements Observer, AsyncListener {
 
 @Override
 public void update(Observable observable, Object event) { 
 synchronized (this) {
 if (event instanceof Notification) {
 handler((Notification) event);
 }
 
 // 
 if (event instanceof Throwable) {
 handlerError((Throwable) event);
 }
 } 
 }
 
 // }
  • 87. class MultipleNotificationStreamObserver implements Observer, AsyncListener {
 
 ReentrantLock reentrantLock = new ReentrantLock();
 
 @Override
 public void update(Observable observable, Object event) {
 
 reentrantLock.lock();
 
 if (event instanceof Notification) {
 handler((Notification) event);
 }
 
 // 
 if (event instanceof Throwable) {
 handlerError((Throwable) event);
 }
 
 reentrantLock.unlock(); 
 }
 
 // }
  • 88.
  • 89. BlockingQueue<Object> notifyQueue = new LinkedBlockingQueue<>(); class SequentialNotifyObserversPublisher implements Runnable {
 
 final Iterator<Notification> notifies;
 final AtomicBoolean running = new AtomicBoolean(true);
 
 SequentialNotifyObserversRunnable(Iterator<Notification> notifies) {
 this.notifies = notifies;
 }
 
 @Override
 public void run() {
 while (running.get()) {
 if (countObservers() > 0) {
 try {
 notifyQueue.put(notifies.next());
 } catch (Exception error) {
 cancel();
 
 try {
 notifyQueue.put(error);
 } catch (InterruptedException ignore) { }
 }
 }
 
 if (Thread.interrupted()) {
 cancel();
 }
 
 Thread.yield();
 }
 }
 
 void cancel() {
 running.set(false);
 }
 
 }
  • 90. class MultipleNotificationStreamObservable extends Observable {
 
 final static ExecutorService executor = Executors.newFixedThreadPool(3);
 
 BlockingQueue<Object> notifyQueue = new LinkedBlockingQueue<>();
 Future<?> notifyFuture;
 
 SequentialNotifyObserversPublisher sequentialFeed;
 SequentialNotifyObserversPublisher sequentialFriend;
 
 public MultipleNotificationStreamObservable(NotificationStream stream) {
 this.sequentialFeed = new SequentialNotifyObserversRunnable(stream.feedNotifies());
 this.sequentialFriend = new SequentialNotifyObserversRunnable(stream.friendRecommendationNotifies());
 }
 
 public void subscribe() {
 executor.execute(sequentialFeed);
 executor.execute(sequentialFriend);
 
 notifyFuture = executor.submit(() -> {
 boolean running = true;
 while (running) {
 if (countObservers() > 0) {
 try {
 Object event = notifyQueue.take();
 
 setChanged();
 notifyObservers(event);
 } catch (InterruptedException e) {
 running = false;
 }
 }
 if (Thread.interrupted()) {
 running = false;
 }
 Thread.yield();
 }
 });
 }
 // 
 }
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97. void printUserInfo(String username) {
 NotifyApi notifyApi = new NotifyApi();
 
 NotifyApi.User user = notifyApi.getUser(username);
 Long feedCount = notifyApi.getFeedCount(username);
 Long friendCount = notifyApi.getFriendCount(username);
 
 UserInfo userInfo = new UserInfo(user.getName(), feedCount, friendCount);
 
 System.out.println("User Info");
 System.out.println("name = " + userInfo.getName());
 System.out.println("feedCount = " + userInfo.getFeedCount());
 System.out.println("friendCount = " + userInfo.getFriendCount());
 } 
 
 printUserInfo("fay"); // 1
 printUserInfo("murphy"); // 2
 printUserInfo("nichole"); // 3
  • 98. void printUserInfo(String username) { … } ExecutorService executorService = Executors.newFixedThreadPool(3); 
 executorService.execute(() -> printUserInfo("fay")); // 1
 executorService.execute(() -> printUserInfo("murphy")); // 2
 executorService.execute(() -> printUserInfo("nichole")); // 3
  • 99. void printUserInfo(String username) { … } ExecutorService executorService = Executors.newFixedThreadPool(3); 
 executorService.execute(() -> printUserInfo("fay")); // 1
 executorService.execute(() -> printUserInfo("murphy")); // 2
 executorService.execute(() -> printUserInfo("nichole")); // 3 
 executorService.execute(() -> printUserInfo("phillip")); // 4
 executorService.execute(() -> printUserInfo("adrienne")); // 5
 executorService.execute(() -> printUserInfo("nita")); // 6
  • 100. ExecutorService executorService = Executors.newFixedThreadPool(1); 
 void printUserInfo(String username) {
 CompletableFuture.supplyAsync(() -> notifyApi.getUser(username), executorService)
 .thenCompose(user -> {
 CompletableFuture<Long> feedCountCF = CompletableFuture.supplyAsync(
 () -> notifyApi.getFeedCount(username), executorService);
 
 CompletableFuture<Long> friendCountCF = CompletableFuture.supplyAsync(
 () -> notifyApi.getFriendCount(username), executorService);
 
 return feedCountCF.thenCombineAsync(friendCountCF, (feedCount, friendCount) -> {
 return new UserInfo(user.getName(), feedCount, friendCount);
 }, executorService);
 })
 .thenAccept(userInfo -> {
 System.out.println("User Info");
 System.out.println("name = " + userInfo.getName());
 System.out.println("feedCount = " + userInfo.getFeedCount());
 System.out.println("friendCount = " + userInfo.getFriendCount());
 });
 }
 
 printUserInfo("fay"); // 1
 printUserInfo("murphy"); // 2
 printUserInfo("nichole"); // 3
  • 101.
  • 102. ExecutorService executorService = Executors.newFixedThreadPool(3); 
 void printUserInfo(String username) {
 // 
 }
 
 
 printUserInfo("fay"); // 1
 printUserInfo("murphy"); // 2
 printUserInfo("nichole"); // 3
 
 printUserInfo("phillip"); // 4
 printUserInfo("adrienne"); // 5
 printUserInfo("nita"); // 6
  • 103. class NotificationPublisher implements Runnable {
 
 Iterator<Notification> notifies;
 
 NotifyObserversRunnable(Iterator<Notification> notifies) {
 this.notifies = notifies;
 }
 
 @Override
 public void run() {
 boolean running = true;
 while (running) {
 if (countObservers() > 0) {
 try {
 Notification notification = notifies.next();
 
 setChanged();
 notifyObservers(notification);
 } catch (Exception error) {
 running = false;
 
 setChanged();
 notifyObservers(error);
 }
 }
 
 if (Thread.interrupted()) {
 running = false;
 }
 
 Thread.yield();
 }
 }
 
 }
  • 104. class NotificationPublisher implements Runnable {
 final Iterator<Notification> notifies;
 final AtomicBoolean running = new AtomicBoolean(true); 
 NotifyObserversRunnable(Iterator<Notification> notifies) {
 this.notifies = notifies;
 }
 
 public void run() {
 if (countObservers() > 0) {
 CompletableFuture<Object> completableFuture = new CompletableFuture<>();
 completableFuture.thenAcceptAsync(event -> {
 if (running.get()) {
 setChanged();
 notifyObservers(event);
 }
 schedule(20);
 }, notifyExecutor).exceptionally(throwable -> {
 cancel();
 setChanged();
 notifyObservers(throwable);
 return null;
 });
 try {
 completableFuture.complete(notifies.next());
 } catch (Exception error) {
 completableFuture.completeExceptionally(error);
 }
 }
 schedule(50);
 } 
 void schedule(long millis) {
 if (running.get()) {
 serviceExecutor.schedule(this, millis, TimeUnit.MILLISECONDS);
 }
 } 
 void cancel() {
 running.set(false);
 }
 }
  • 105. class AsyncMultipleNotificationStreamObservable extends Observable {
 
 final static ScheduledExecutorService serviceExecutor = Executors.newScheduledThreadPool(2);
 final static ScheduledExecutorService notifyExecutor = Executors.newScheduledThreadPool(1);
 
 NotifyObserversRunnable feedPublisher;
 NotifyObserversRunnable friendPublisher;
 
 public AsyncMultipleNotificationStreamObservable(NotificationStream stream) {
 this.feedPublisher = new NotifyObserversRunnable(requireNonNull(stream).feedNotifies());
 this.friendPublisher = new NotifyObserversRunnable(requireNonNull(stream).friendRecommendationNotifies());
 }
 
 public void subscribe() {
 serviceExecutor.schedule(feedPublisher, 10, TimeUnit.MILLISECONDS);
 serviceExecutor.schedule(friendPublisher, 10, TimeUnit.MILLISECONDS);
 }
 
 public void unsubscribe() {
 feedPublisher.cancel();
 friendPublisher.cancel();
 } }
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112. SocketChannel channel = SocketChannel.open();
 channel.configureBlocking(true);
 
 Socket socket = channel.socket();
 socket.connect(new InetSocketAddress("www.naver.com", 80));
 
 BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 PrintStream output = new PrintStream(socket.getOutputStream());
 
 output.println("GET / HTTP/1.0");
 output.println();
 
 StringBuilder response = new StringBuilder();
 String line = input.readLine();
 while (Objects.nonNull(line)) {
 response.append(line).append("n");
 line = input.readLine();
 
 // body 
 if ("".equals(line)) {
 while (Objects.nonNull(line)) {
 line = input.readLine();
 }
 }
 }
 
 input.close();
 output.close();
  • 113.
  • 114.
  • 116. Selector selector = Selector.open();
 
 SocketChannel socketChannel = SocketChannel.open();
 socketChannel.configureBlocking(false);
 
 socketChannel.connect(new InetSocketAddress("www.naver.com", 80));
 socketChannel.register(selector, SelectionKey.OP_CONNECT);
 
 while (socketChannel.isOpen()) {
 if (selector.select() > 0) {
 Set<SelectionKey> selectionKeys = selector.selectedKeys();
 Iterator<SelectionKey> iterator = selectionKeys.iterator();
 
 while (iterator.hasNext()) {
 SelectionKey selectionKey = iterator.next();
 
 if (selectionKey.isConnectable()) {
 SocketChannel channel = (SocketChannel) selectionKey.channel(); 
 // 
 } else if (selectionKey.isWritable()) {
 SocketChannel channel = (SocketChannel) selectionKey.channel();
 
 // 
 
 } else if (selectionKey.isReadable()) {
 SocketChannel channel = (SocketChannel) selectionKey.channel();
 
 // 
 
 }
 // 
 iterator.remove();
 }
 }
 }
  • 117.
  • 118. AsynchronousChannelGroup asynchronousChannelGroup = AsynchronousChannelGroup.withFixedThreadPool(1); AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open(asynchronousChannelGroup); SocketAddress socketAddress = new InetSocketAddress(“www.naver.com”, 80);
 
 asynchronousSocketChannel.connect(socketAddress, null, new CompletionHandler<Void, Void>() {
 @Override
 public void completed(Void v, Void attachment) {
 // 
 asynchronousSocketChannel.write(writeBuffer, null, new CompletionHandler<Integer, Void>() {
 @Override
 public void completed(Integer length, Void attachment) { // 
 asynchronousSocketChannel.read(readBuffer, null, new CompletionHandler<Integer, Void>() {
 @Override
 public void completed(Integer length, Void attachment) { // }
 @Override
 public void failed(Throwable error, Void attachment) {
 // 
 }
 });
 }
 @Override
 public void failed(Throwable error, Void attachment) {
 // 
 }
 });
 }
 @Override
 public void failed(Throwable exc, Void attachment) {
 // 
 }
 });
  • 119.
  • 120.
  • 121. ✔ Netty(http://netty.io) ✔ gRPG(http://www.grpc.io) ✔ AsyncHttpClient(https://hc.apache.org/)
  • 122. public FriendRecommendationNotify getRecommendationNotify(String username) throws ServiceOperationException {
 try {
 HttpGet request = new HttpGet(String.format(url, username, processing.name()));
 HttpResponse response = httpClient.execute(request);
 if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
 throw new ServiceOperationException();
 }
 
 return objectMapper.readValue(response.getEntity().getContent(), FriendRecommendationNotify.class);
 } catch (IOException error) {
 throw new ServiceOperationException(error);
 }
 }
  • 123. public CompletableFuture<FriendRecommendationNotify> getRecommendationNotifyAsync(String username) {
 CompletableFuture<FriendRecommendationNotify> completableFuture = new CompletableFuture<>();
 
 HttpGet request = new HttpGet(String.format(url, username, processing.name()));
 httpAsyncClient.execute(request, new FutureCallback<HttpResponse>() {
 
 @Override
 public void completed(HttpResponse response) {
 try {
 int statusCode = response.getStatusLine().getStatusCode();
 InputStream content = response.getEntity().getContent();
 
 if (statusCode != HttpStatus.SC_OK) {
 completableFuture.completeExceptionally(new ServiceOperationException());
 }
 
 completableFuture.complete(objectMapper.readValue(content, FriendRecommendationNotify.class));
 } catch (IOException error) {
 completableFuture.completeExceptionally(new ServiceOperationException(error));
 }
 }
 
 @Override
 public void failed(Exception error) {
 completableFuture.completeExceptionally(error);
 }
 
 @Override
 public void cancelled() {
 completableFuture.cancel(true);
 }
 
 });
 
 return completableFuture;
 }
  • 124. @Test
 public void getRecommendationNotify() throws Exception {
 StopWatch stopWatch = new StopWatch("recommendationNotify");
 stopWatch.start();
 
 IntStream.rangeClosed(1, 10)
 .mapToObj(value -> friendService.getRecommendationNotify("user-" + value))
 .forEach(System.out::println);
 
 stopWatch.stop();
 System.out.println();
 System.out.println(stopWatch.prettyPrint());
 }
 
 @Test
 public void getRecommendationNotifyAsync() throws Exception {
 StopWatch stopWatch = new StopWatch("recommendationNotifyAsync");
 stopWatch.start();
 
 IntStream.rangeClosed(1, 10)
 .mapToObj(value -> friendService.getRecommendationNotifyAsync("user-" + value))
 .collect(Collectors.toList())
 .stream()
 .map(CompletableFuture::join)
 .forEach(System.out::println);
 
 stopWatch.stop();
 System.out.println();
 System.out.println(stopWatch.prettyPrint());
 }
  • 125. class NotificationPublisher implements Runnable {
 
 final Supplier<CompletableFuture<Notification>> notifies;
 final AtomicBoolean running = new AtomicBoolean(true);
 
 NotifyObserversRunnable(Supplier<CompletableFuture<Notification>> notifies) {
 this.notifies = notifies;
 }
 
 @Override
 public void run() {
 if (countObservers() > 0) {
 notifies.get().thenAcceptAsync(event -> {
 if (running.get()) {
 setChanged();
 notifyObservers(event);
 }
 
 schedule(20);
 }, notifyExecutor).exceptionally(throwable -> {
 cancel();
 setChanged();
 notifyObservers(throwable);
 
 return null;
 });
 } else {
 schedule(50);
 }
 }
 
 void schedule(long millis) {
 if (running.get()) {
 serviceExecutor.schedule(this, millis, TimeUnit.MILLISECONDS);
 }
 }
 
 void cancel() {
 running.set(false);
 }
 }
  • 126. class NonBlockingAsyncMultipleNotificationStreamObservable extends Observable {
 
 final static ScheduledExecutorService serviceExecutor = Executors.newScheduledThreadPool(1);
 final static ScheduledExecutorService notifyExecutor = Executors.newScheduledThreadPool(1);
 
 NotifyObserversRunnable feed;
 NotifyObserversRunnable friend;
 
 public NonBlockingAsyncMultipleNotificationStreamObservable(NotificationStream stream) {
 requireNonNull(stream);
 
 this.feed = new NotifyObserversRunnable(stream::feedNotifyAsync);
 this.friend = new NotifyObserversRunnable(stream::friendRecommendationNotifyAsync);
 }
 
 public void subscribe() {
 serviceExecutor.execute(feed);
 serviceExecutor.execute(friend);
 }
 
 public void unsubscribe() {
 if (nonNull(feed)) feed.cancel();
 if (nonNull(friend)) friend.cancel();
 
 deleteObservers();
 }
 }
  • 127.
  • 128.
  • 129.
  • 130. class NonBlockingAsyncMultipleNotificationStreamObserver implements Observer, AsyncListener {
 
 final NonBlockingAsyncMultipleNotificationStreamObservable streamObservable;
 final AsyncContext asyncContext;
 
 public NonBlockingAsyncMultipleNotificationStreamObserver(N…Observable streamObservable, AsyncContext asyncContext) {
 this.streamObservable = Objects.requireNonNull(streamObservable);
 this.asyncContext = Objects.requireNonNull(asyncContext);
 }
 
 @Override
 public void update(Observable observable, Object event) {
 if (event instanceof Notification) {
 handler((Notification) event);
 }
 
 if (event instanceof Throwable) {
 handlerError((Throwable) event);
 }
 }
 
 private void handler(Notification notification) {
 try {
 log.info("revised notification/stream/non-blocking-async-concurrency : " + notification.getEvent());
 
 ServletOutputStream outputStream = asyncContext.getResponse().getOutputStream();
 outputStream.write(("event: " + notification.getEvent() + "n").getBytes());
 outputStream.write(("data: " + notification.getData() + "nn").getBytes());
 outputStream.flush();
 } catch (IOException error) {
 throw new DataWriteException(error);
 }
 }
 
 private void handlerError(Throwable error) {
 log.error("error notification/stream/non-blocking-async-concurrency : " + error.getMessage());
 
 streamObservable.unsubscribe();
 asyncContext.complete();
 }
 }
  • 131. ✔ 비봉쇄 입/출력을 위한 새로운 인터페이스 •ReadListener - 사용 가능한 데이터를 읽을 수 있는 방법 •WriteListener - 데이터 쓰기가 가능한 때를 알 수 있는 방법 ✔ ServletInputStream 에 추가된 기능 •isFinished() •isReady() •setReadListener() ✔ ServletOutputStream 에 추가된 기능 •isReady() •setWriterListener()
  • 132. ServletInputStream servletInputStream = request.getInputStream();
 servletInputStream.setReadListener(new ReadListener() {
 
 @Override
 public void onDataAvailable() throws IOException {
 // 
 }
 
 @Override
 public void onAllDataRead() throws IOException {
 // 
 }
 
 @Override
 public void onError(Throwable throwable) {
 // 
 }
 
 }); ServletOutputStream servletOutputStream = response.getOutputStream();
 servletOutputStream.setWriteListener(new WriteListener() {
 
 @Override
 public void onWritePossible() throws IOException {
 // 
 }
 
 @Override
 public void onError(Throwable throwable) {
 // 
 }
 
 });
  • 133. class NonBlockingAsyncMultipleNotificationStreamObserver implements Observer, AsyncListener, WriteListener {
 
 final NonBlockingAsyncMultipleNotificationStreamObservable streamObservable;
 final AsyncContext asyncContext;
 final ServletOutputStream outputStream;
 
 final AtomicInteger counter = new AtomicInteger(1);
 
 public NonBlockingAsyncMultipleNotificationStreamObserver(N…Observable streamObservable, AsyncContext asyncContext) {
 this.streamObservable = Objects.requireNonNull(streamObservable);
 this.asyncContext = Objects.requireNonNull(asyncContext);
 this.outputStream = asyncContext.getResponse().getOutputStream();
 }
 // 
 @Override
 public void onWritePossible() throws IOException {
 // ignore
 }
 
 @Override
 public void onError(Throwable throwable) {
 handlerError(throwable);
 }
 
 private void handler(Notification notification) {
 String content = notification.toContent();
 
 ioExecutor.schedule(() -> write(content.getBytes()), 10, TimeUnit.MILLISECONDS);
 }
 private void handlerError(Throwable error) {
 log.error("error notification/stream/non-blocking-async-concurrency : " + error.getMessage());
 
 streamObservable.unsubscribe();
 asyncContext.complete();
 } // …
  • 134. // final static ScheduledExecutorService ioExecutor = Executors.newScheduledThreadPool(1); 
 private void write(byte[] data) {
 if (outputStream.isReady()) {
 try {
 outputStream.write(data);
 
 ioExecutor.schedule(this::flush, 10, TimeUnit.MILLISECONDS);
 } catch (IOException error) {
 handlerError(error);
 }
 } else {
 ioExecutor.schedule(() -> write(data), 10, TimeUnit.MILLISECONDS);
 }
 }
 
 private void flush() {
 if (outputStream.isReady()) {
 try {
 outputStream.flush();
 } catch (IOException error) {
 handlerError(error);
 }
 } else {
 ioExecutor.schedule(this::flush, 10, TimeUnit.MILLISECONDS);
 }
 }
 
 }
  • 135.