users@grizzly.java.net

RE: From Grizzly 1.9.x to 2.x

From: Gay David (Annecy) <"Gay>
Date: Fri, 5 Aug 2011 17:36:06 +0000

Hi Alexey,

Yes, sorry about mis-understading the true/false parameter of getInputStream(). Shame on me !

I try to do async as you suggest, the async way.
But, my readHandler isn't call at all.
Does this seems ok to you ?

public class ResourceUploadAsyncImpl
        implements ReadHandler
{
    // Constants
    private static final Logger log = Logger.getLogger( ResourceUploadAsyncImpl.class.getName() );
    private static final int WHEN_AVAILABLE_SIZE = 8 * 1024;

    // Internal Fields
    private Request req;
    private Response res;
    private WritableByteChannel channel;
    private Exception error;
    private NIOInputStream in;


    //--- Constructor ----------------------------------------------------------

    public ResourceUploadAsyncImpl( Request req, Response res, OutputStream os )
    {
        this.req = req;
        this.res = res;

        this.channel = Channels.newChannel( os );
        this.error = null;
    }


    //--- Public methods -------------------------------------------------------

    public void go()
    {
        in = req.getInputStream( false );
                   in.notifyAvailable( this, WHEN_AVAILABLE_SIZE );
    }


    //--- ReadHandler implementation -------------------------------------------

    @Override
    public void onDataAvailable()
        throws Exception
    {
        transferAvailableData();
        in.notifyAvailable( this );
    }

    @Override
    public void onError( Throwable t )
    {
        error = new Exception( "Problem", t );
        res.setStatus( HttpStatus.INTERNAL_SERVER_ERROR_500 );
        finish();
    }

    @Override
    public void onAllDataRead()
        throws Exception
    {
        transferAvailableData();
        res.setStatus( HttpStatus.OK_200 );
        finish();
    }

    //--- Private methods ------------------------------------------------------

    private void transferAvailableData()
        throws IOException
    {
        Buffer buffer;
        ByteBuffer bb;

        buffer = in.getBuffer();
        bb = buffer.toByteBuffer();
        try
        {
            while( bb.hasRemaining() )
            {
                channel.write( bb );
            }
        }
        finally
        {
            buffer.tryDispose();
        }
    }

    private void finish()
    {
        // Close the output
        try
        {
            channel.close();
        }
        catch( Exception ex )
        {
            log.log( SEVERE, "Error while closing the channel", ex );
            if( error != null )
            {
                error = ex;
                res.setStatus( HttpStatus.INTERNAL_SERVER_ERROR_500 );
            }
        }

        // Close the input
        try
        {
            in.close();
        }
        catch( Exception ex )
        {
            log.log( SEVERE, "Error while closing the input", ex );
            if( error != null )
            {
                error = ex;
                res.setStatus( HttpStatus.INTERNAL_SERVER_ERROR_500 );
            }
        }

        // And resume
        res.resume();
    }

}

BTW : the response is already suspended somewhere else in my code ...

I see in the exemple you gave to me that the method Buffer.readBuffer() is called.
But I have only the the method Buffer.getBuffer() available.
Anyway, theses methods are never called.

Maybe the async is only available on trunk version and not on the 2.1.1 ?

I really hope I don't make another stupid mistake this time :-(


Thanks and regards
David

De : Oleksiy Stashok [mailto:oleksiy.stashok_at_oracle.com]
Envoyé : jeudi 4 août 2011 10:44
À : users_at_grizzly.java.net
Objet : Re: From Grizzly 1.9.x to 2.x

Hi David,

checked the sample you sent one more time.
First of all it doesn't work, cause you try to use non-blocking InputStream as it was blocking, so when you change code like this (change false -> true):

    public boolean upload() {
        boolean finish;
        int read;

        finish = false;
        try {
            read = req.getInputStream(true).read(buffer);


it starts to work.

But as I understand in your sample you're actually trying to simulate non-blocking upload, and IMO it would make sense to use non-blocking InputStream. Please check this sample [1] and documentation [2], it may help you to understand non-blocking InputStream better.

Thanks.

WBR,
Alexey.


[1] http://java.net/projects/grizzly/sources/git/content/samples/http-server-samples/src/main/java/org/glassfish/grizzly/samples/httpserver/nonblockinghandler/UploadHttpHandlerSample.java
[2] http://grizzly.java.net/nonav/docs/docbkx2.0/html/hsf-nio-streams.html



On 08/03/2011 04:33 PM, Gay David (Annecy) wrote:
Hi all,

I'm trying to experiment Grizzly 2 by porting my current application from 1.9.x to 2.x.

Basically I'm assuming that the default Grizzly behavior is the same to do long request :

* Suspend the response
* Give the processing of the request/response to my own thread pool
* Once finish, resume it

Am I wrong ?

So my first step is to convert all my code that use Gz 1.9 API to Gz 2.0 API (package change, etc.) and check how it works (and also check if it's fix some problems I have under heavy load).

The second step would be later to use new functionality of Gz 2.0

So I've done the first step, but I'm block on some units test that simulate some heavy upload/download. (unit tests that went ok with Gz 1.9.x)


I've made a simple test case to illustrate my problem. This test simulate uploads, but I still have to same problem with download.
I've add it in attachement, it's a simple Maven project.

At the end of the (long) test, I've many exception like :

java.lang.IllegalStateException: Internal org.glassfish.grizzly.http.server.Response has not been set
        at org.glassfish.grizzly.http.server.Response.checkResponse(Response.java:1607)
        at org.glassfish.grizzly.http.server.Response.setStatus(Response.java:1255)
        at org.glassfish.grizzly.http.server.HttpHandlerChain.service(HttpHandlerChain.java:202)
        at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:162)
        at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:160)
        at org.glassfish.grizzly.filterchain.ExecutorResolver$3.execute(ExecutorResolver.java:95)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:444)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:364)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:290)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:133)
        at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:76)
        at org.glassfish.grizzly.filterchain.FilterChainContext$1.run(FilterChainContext.java:198)
        at org.glassfish.grizzly.filterchain.FilterChainContext.resume(FilterChainContext.java:222)
        at org.glassfish.grizzly.http.server.Response.cancel(Response.java:1599)
        at org.glassfish.grizzly.http.server.Response$SuspendedContextImpl.onClosed(Response.java:1717)
        at org.glassfish.grizzly.nio.NIOConnection.notifyCloseListeners(NIOConnection.java:612)
        at org.glassfish.grizzly.nio.NIOConnection.close(NIOConnection.java:358)
        at org.glassfish.grizzly.nio.NIOConnection.close(NIOConnection.java:349)
        at org.glassfish.grizzly.nio.SelectorRunner.shutdownSelector(SelectorRunner.java:210)
        at org.glassfish.grizzly.nio.SelectorRunner.run(SelectorRunner.java:286)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:508)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:488)
        at java.lang.Thread.run(Thread.java:662)

Could someone helps me to check if I do something wrong, or if it's a Gz 2.x problem.

BTW : I'm using Grizzly 2.1.1

Thanks and regards
David