<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>leine.info &#187; AJAX</title>
	<atom:link href="http://leine.info/tag/ajax/feed/" rel="self" type="application/rss+xml" />
	<link>http://leine.info</link>
	<description>Discover my public and private World.</description>
	<lastBuildDate>Thu, 22 Dec 2011 13:57:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Schöne neue AJAX Welt mit Servlet 3.0</title>
		<link>http://leine.info/2009/02/schone-neue-ajax-welt-mit-servlet-30/</link>
		<comments>http://leine.info/2009/02/schone-neue-ajax-welt-mit-servlet-30/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 07:00:15 +0000</pubDate>
		<dc:creator>jleine</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Servlet 3.0]]></category>

		<guid isPermaLink="false">http://leine.info/?p=196</guid>
		<description><![CDATA[Vor kurzem habe ich mir die Servlet 3.0 Spezifikation etwas näher angesehen. Was mir dabei zuerst ins Auge fiel war das Tag @WebServlet mit seinem neuen asyncSupported Attribut. Das machte mich natürlich neugierig und ich forschte noch ein wenig weiter. &#8230; <a href="http://leine.info/2009/02/schone-neue-ajax-welt-mit-servlet-30/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Vor kurzem habe ich mir die Servlet 3.0 Spezifikation etwas näher angesehen. Was mir dabei zuerst ins Auge fiel war das Tag <strong>@WebServlet</strong> mit seinem neuen <strong>asyncSupported</strong> Attribut. Das machte mich natürlich neugierig und ich forschte noch ein wenig weiter.</p>
<p>Es stellte sich heraus das, mit der neuen Servlet 3.0 Spezifikation, Servlets einen AJAX Support aufweisen. Doch was bedeutet dies genau? Ein wirklich sehr guter Artikel auf <a href="http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html">JavaWorld.com</a>brachte mir die Erkenntnis. <span id="more-196"></span></p>
<p>Jedes mal wenn ein Client einen Request an einen Webserver stellt, und das kann in der heutigen AJAX Zeit sehr oft der Fall sein, wird ein neuer Server Thread diesem Client Request zugeteilt. Je nach Implementierungslogik kann es sehr lange dauern bis dieser Request beantwortet wird, z.B. weil zuerst eine JDBC Verbindung aufgebaut werden muss, etc. Solange der Request nicht gegen einen Timeout läuft verbleibt dieser mit all seinen belegten Ressourcen offen. Diesem UseCase kann man natürlich entgegenwirken, indem z.B. AJAX Polling Mechanismen immer wieder nach dem Status fragen, Servlets neue Threads erzeugen, die die Verarbeitung des Client Requests abarbeiten, und dem Client über einen Status mitteilen ob ihr Ergebnis fertig ist oder nicht.</p>
<p>Der Servlet 3.0 Ansatz verfolgt eine etwas andere Strategie, indem er den Client aktiv benachrichtigt (PUSH). Quellcode sagt hier vielleicht mehr als tausen Worte, deswegen ein kurzes Beispiel.</p>
<pre name="code" class="java">
@WebServlet(name="myServlet", urlPatterns={"/auctionservice"}, asyncSupported=true)
public class MyServlet extends HttpServlet {

   // track bid prices
   public void doGet(HttpServletRequest request, HttpServletResponse response) {
      AsyncContext aCtx = request.startAsync(request, response);
      // This could be a cluser-wide cache.
      ServletContext appScope = request.getServletContext();
      Map<String, List<AsyncContext>> aucWatchers = (Map<String, List<AsyncContext>>)appScope.getAttribute("aucWatchers");
      List<AsyncContext> watchers = (List<AsyncContext>)aucWatchers.get(request.getParameter("auctionId"));
      watchers.add(aCtx); // register a watcher
   }

   // place a bid
   public void doPost(HttpServletRequest request, HttpServletResponse response) {
      // run in a transactional context
      // save a new bid
      AsyncContext aCtx = request.startAsync(request, response);
      ServletContext appScope = request.getServletContext();
      Queue<Bid> aucBids = (Queue<Bid>)appScope.getAttribute("aucBids");
      aucBids.add((Bid)request.getAttribute("bid"));  // a new bid event is placed queued.
   }
}

@WebServletContextListener
public class BidPushService implements ServletContextListener{

   public void contextInitialized(ServletContextEvent sce) {
      Map<String, List<AsyncContext>> aucWatchers = new HashMap<String, List<AsyncContext>>();
      sce.getServletContext().setAttribute("aucWatchers", aucWatchers);
      // store new bids not published yet
      Queue<Bid> aucBids = new ConcurrentLinkedQueue<Bid>();
      sce.getServletContext().setAttribute("aucBids", aucBids);

      Executor bidExecutor = Executors.newCachedThreadPool();
      final Executor watcherExecutor = Executors.newCachedThreadPool();
      while(true)
      {
         if(!aucBids.isEmpty()) // There are unpublished new bid events.
         {
            final Bid bid = aucBids.poll();
            bidExecutor.execute(new Runnable(){
               public void run() {
                  List<AsyncContext> watchers = aucWatchers.get(bid.getAuctionId());
                  for(final AsyncContext aCtx : watchers)
                  {
                     watcherExecutor.execute(new Runnable(){
                        public void run() {
                           // publish a new bid event to a watcher
                           aCtx.getResponse().getWriter().print("A new bid on the item was placed. The current price ..., next bid price is ...");
                        };
                     });
                  }
               }
            });
         }
      }
   }

   public void contextDestroyed(ServletContextEvent sce) {
   }
}
</pre>
<p>Wie man sieht werden die beiden üblichen Methoden, doGet und doPost, des Servlets sehr schnell abgearbeitet, indem ein sog. AsyncContext erzeugt wird. Über diesen Context hat man dann die Möglichkeit den Client asynchron eine Antwort zu schicken (PUSH). In meinen Augen eine sehr elegante Implementierungsmöglichkeit.</p>
<p>Bleibt allerdings nur noch eine Frage offen. Was ist im Endeffekt schlimmer? Ein ständiger kurzer Polling Mechanismus durch den Client oder eine Pushvariante nach dem Streaming oder Long Polling Mechanismus. Nun, letztendlich bleibt einem nichts weiter übrig als die Serlvet 3.0 Spezifikation abzuwarten und das Ergebnis selbst einmal auszuprobieren.</p>
]]></content:encoded>
			<wfw:commentRss>http://leine.info/2009/02/schone-neue-ajax-welt-mit-servlet-30/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

