users@glassfish.java.net

Re: servlet 3.0 async, gfv3

From: Jan Luehe <Jan.Luehe_at_Sun.COM>
Date: Tue, 13 Apr 2010 21:44:13 -0700

emiddio-verizon wrote:
> it was a behaviour observed in the servlet -- is why its related --i
> bunched all my questions together.
>
> i have also seen the behaviour in the gfv3 samples web app --
> async-request-war project --
> which fails to work properly -- it claims to be a modified grizzly
> sample -- but the grizzly sample
> which uses comet does work; but this sample does not -- yesterday
> while debugging it -- i caught
> its init() being called for each message being posted in the web app
> form. -- and each init
> create a new thread for dealing with a new message queue -- but this
> is off topic.
>
>
> the fact is init() is being called for each servlet invocation -- at
> least for async servlets.
> i have not checked if happening for non-async servlets.
>
>
> my interest was in the async perhaps more precisly in a posting to the
> servlet forum --
> here copied/pasted
> -------------------------
> i am experimenting with servlet 3.0 async with gfv3; my servlet's
> init() method is being called for each browser web request -- i
> thought only 1 init() call per servlet ??

Yes, only one init per Servlet, regardless of whether the Servlet is
declared to support async operations. Shing Wai has confirmed in an
earlier email that this is the case.
>
> destroy is only being called when i undeploy the servlets -- 2
> servlets in 1 web app.
>
> i am trying to experiment with all the options that apply to async
> support.
>
> i have not figured how i am suppose to use AsycnContext.complete(); if
> i async.dispach to another servlet -- that servlet cannot
> call AsyncContext.complete();

Why not?
>
> also --
>
> the AsyncListener class -- has method onStartAsync() -- i am searching
> for a way to cause that method to be called ?
>

I've included the Servlet from one of our unit tests. It exercises all
the async features you've inquired about. The expected response from it
is "onStartAsync,onStartAsync,onComplete". This Servlet implements the
AsyncListener interface and registers itself as an AsnycListener with
the AsyncContext created by the first call to ServletRequest#startAsync.
This AsyncContext is reinitialized by a subsequent call to
ServletRequest#startAsync during an async dispatch. The second call to
ServletRequest#startAsync invokes the Servlet (implementing the
AsyncListener interface) at its onStartAsync method, which the Servlet
uses to renew its registration with the AsyncContext.


Jan

> any help in understand will be appreciated.
> -------------
>
> thanks
>
> gary
>
>
> ----- Original Message -----
> *From:* Shing Wai Chan <mailto:shing.wai.chan_at_oracle.com>
> *To:* users_at_glassfish.dev.java.net
> <mailto:users_at_glassfish.dev.java.net>
> *Sent:* Tuesday, April 13, 2010 6:25 PM
> *Subject:* Re: servlet 3.0 async, gfv3
>
> On 4/13/2010 6:03 PM, Shing Wai Chan wrote:
>> The servlet init() should only be called once for a given servlet.
> I have confirmed that this is correct in GlassFish v3.
> Btw, how is it related to async described in the email subject?
>
>> Shing Wai Chan
>>
>> On 4/13/2010 5:37 PM, emiddio-verizon wrote:
>>> i am experimenting with servlet 3.0 async with gfv3;
>>>
>>> but i am confused -- i thought the servlet's init() method was
>>> only to be called 1 time -- at
>>> servlet initialization ???
>>>
>>> i am seeing init() being called for each browser web request.
>>>
>>> destroy is only being called when i undeploy the servlet
>>>
>>> this seems wrong to my understanding.
>>>
>>> gary
>>>
>>>
>>>
>>
>




/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2010 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License"). You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 *
 * Contributor(s):
 *
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license." If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above. However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package test;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends HttpServlet implements AsyncListener {

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {

        if (!req.isAsyncSupported()) {
            throw new ServletException("Async not supported when it should");
        }
   
        if (req.getDispatcherType() == DispatcherType.REQUEST) {
            // Container-initiated dispatch
            req.setAttribute("ABC", "DEF");
            final AsyncContext ac = req.startAsync();
            ac.addListener(this);
            Timer asyncTimer = new Timer("AsyncTimer", true);
            asyncTimer.schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        ac.dispatch();
                    }
                },
                5000);
        } else if (req.getDispatcherType() == DispatcherType.ASYNC) {
            if ("DEF".equals(req.getAttribute("ABC"))) {
                // First async dispatch
                req.removeAttribute("ABC");
                req.startAsync().dispatch();
            } else {
                // Second async dispatch
                req.startAsync().complete();
            }
        }
    }

    public void onComplete(AsyncEvent event) throws IOException {
        event.getAsyncContext().getResponse().getWriter().println(
            "onComplete");
    }

    public void onTimeout(AsyncEvent event) throws IOException {
        // do nothing
    }

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

    public void onStartAsync(AsyncEvent event) throws IOException {
        event.getAsyncContext().getResponse().getWriter().print(
            "onStartAsync,");
        /*
         * ServletRequest#startAsync clears the list of AsyncListener
         * instances registered with the AsyncContext - after calling
         * each AsyncListener at its onStartAsync method, which is the
         * method we're in.
         * Register ourselves again, so we continue to get notified
         */
        event.getAsyncContext().addListener(this);
    }

}