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

마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트)
마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트) 마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트)
마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트) Amazon Web Services Korea
 
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...HostedbyConfluent
 
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...New Relic
 
Event Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQEvent Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQAraf Karsh Hamid
 
RESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsRESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsQASymphony
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...Yevgeniy Brikman
 
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기YongSung Yoon
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향Young-Ho Cho
 
Microservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaMicroservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaAraf Karsh Hamid
 
MSA ( Microservices Architecture ) 발표 자료 다운로드
MSA ( Microservices Architecture ) 발표 자료 다운로드MSA ( Microservices Architecture ) 발표 자료 다운로드
MSA ( Microservices Architecture ) 발표 자료 다운로드Opennaru, inc.
 
스프링 부트와 로깅
스프링 부트와 로깅스프링 부트와 로깅
스프링 부트와 로깅Keesun Baik
 
Chaos Engineering 101: A Field Guide
Chaos Engineering 101: A Field GuideChaos Engineering 101: A Field Guide
Chaos Engineering 101: A Field Guidematthewbrahms
 
Cypress-vs-Playwright: Let the Code Speak
Cypress-vs-Playwright: Let the Code SpeakCypress-vs-Playwright: Let the Code Speak
Cypress-vs-Playwright: Let the Code SpeakApplitools
 
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)Konveyor Community
 
Comprehensive Terraform Training
Comprehensive Terraform TrainingComprehensive Terraform Training
Comprehensive Terraform TrainingYevgeniy Brikman
 
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin Kim
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin KimAWS Innovate: Mobile App testing with AWS Device Farm- Kevin Kim
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin KimAmazon Web Services Korea
 

What's hot (20)

마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트)
마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트) 마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트)
마이크로서비스 기반 클라우드 아키텍처 구성 모범 사례 - 윤석찬 (AWS 테크에반젤리스트)
 
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
Building an Interactive Query Service in Kafka Streams With Bill Bejeck | Cur...
 
Springboot Microservices
Springboot MicroservicesSpringboot Microservices
Springboot Microservices
 
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...
SRE-iously: Defining the Principles, Habits, and Practices of Site Reliabilit...
 
Event Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQEvent Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQ
 
RESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsRESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and Jenkins
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
 
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향
 
Maven tutorial
Maven tutorialMaven tutorial
Maven tutorial
 
Microservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaMicroservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and Saga
 
MSA ( Microservices Architecture ) 발표 자료 다운로드
MSA ( Microservices Architecture ) 발표 자료 다운로드MSA ( Microservices Architecture ) 발표 자료 다운로드
MSA ( Microservices Architecture ) 발표 자료 다운로드
 
스프링 부트와 로깅
스프링 부트와 로깅스프링 부트와 로깅
스프링 부트와 로깅
 
Maven Introduction
Maven IntroductionMaven Introduction
Maven Introduction
 
Chaos Engineering 101: A Field Guide
Chaos Engineering 101: A Field GuideChaos Engineering 101: A Field Guide
Chaos Engineering 101: A Field Guide
 
Cypress-vs-Playwright: Let the Code Speak
Cypress-vs-Playwright: Let the Code SpeakCypress-vs-Playwright: Let the Code Speak
Cypress-vs-Playwright: Let the Code Speak
 
Introduction to Microservices
Introduction to MicroservicesIntroduction to Microservices
Introduction to Microservices
 
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)
[Konveyor] introduction to cloud native chaos engineering with litmus chaos (1)
 
Comprehensive Terraform Training
Comprehensive Terraform TrainingComprehensive Terraform Training
Comprehensive Terraform Training
 
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin Kim
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin KimAWS Innovate: Mobile App testing with AWS Device Farm- Kevin Kim
AWS Innovate: Mobile App testing with AWS Device Farm- Kevin Kim
 

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
 
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 (10)

우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
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

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 

Recently uploaded (20)

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 

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.