Hi Ivy team

I want to build a JAX-RS API returning response in a streaming manner (chunked transfer encoding). The code looks like below:

@Path("{applicationName}/streams")
public class StreamingResponseRestSResource {

    @GET
    public Response getStreamingResponse() {

        // This works by keeping a reference then pass it to the anonymous class.
        // It may NOT work in all situations.
        final Logger logger = Ivy.log();


        StreamingOutput streamingOutput = new StreamingOutput() {

            @Override
            public void write(OutputStream output) throws IOException,
                    WebApplicationException {

                PrintWriter out = new PrintWriter(new BufferedWriter(
                        new OutputStreamWriter(output)), true);

                Ivy.log().error("HHH - BREAK HERE");

                logger.error("HHH - It works with passed reference of Logger");

                IntStream.range(0, 100_000)
                    .forEach(c -> out.println("HHH - Count up to " + c));

            }
        };

        return Response.ok(streamingOutput).build();
    }
}

Full code here: http://pastebin.com/tEAMGFB3

If I do

curl -i -u Developer:Developer http://localhost:8081/ivy/api/designer/streams

the response would be:

{ "errorId": "1578A42A15718503", "errorMessage": "Access to ivy environment outside a process request thread is not possible.\nCurrent thread: Thread[http-nio-8081-exec-14,5,main]", "statusCode": 500 }

If I comment out the line ...

Ivy.log().error("HHH - BREAK HERE");

...the error disappears.

Is there anyway to fix the access to Ivy with StreamingOutput implementation?

asked 03.10.2016 at 14:50

Genzer%20Hawker's gravatar image

Genzer Hawker
(suspended)
accept rate: 66%


You can achieve it by using internal API that can change in future versions without any comment.

Use a custom StreamingOutput class which does the ivy context setup:

public abstract class IvyStreamingOutput implements StreamingOutput {

    private final IProcessModelVersion pmv;
    private final ISession session;

    public IvyStreamingOutput()
    {
        this(MetaData.getProcessModelVersion(), MetaData.getSession());
    }

    public IvyStreamingOutput(IProcessModelVersion pmv, ISession session) 
    {
        this.pmv = pmv;
        this.session = session;
    }

    @Override
    public final void write(OutputStream stream) 
            throws IOException, WebApplicationException 
    {
        IProcessModelVersionRequest streamRequest = RequestFactory.createRestRequest(pmv, session);
        MetaData.pushRequest(streamRequest);
        try
        {
          writeInIvyContext(stream);
        }
        finally
        {
          MetaData.popRequest();
        }
    }

    public abstract void writeInIvyContext(OutputStream stream)
            throws IOException, WebApplicationException ;

}

Then you can implement any logic that requires the Ivy.XYZ() methods within the writeInIvyContext(OutputStream stream) method.

link

answered 03.10.2016 at 16:44

Reguel%20Wermelinger's gravatar image

Reguel Werme... ♦♦
9.4k31958
accept rate: 70%

edited 03.10.2016 at 16:49

Wow, it works like a charm. However, this will remain as an unofficially supported trick from now on?

(03.10.2016 at 18:43) Genzer Hawker Genzer%20Hawker's gravatar image

If we change the internal code some when, we can talk about whether it makes sense to include something likes this IvyStreamingOutput in our core code. Or maybe it's better to bind a custom implementation of the StreamingOutputProvider in our core. But for now I think it's a good and simple solution which can be used in a real world project.

(04.10.2016 at 15:05) Reguel Werme... ♦♦ Reguel%20Wermelinger's gravatar image
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×147
×33

Asked: 03.10.2016 at 14:50

Seen: 3,310 times

Last updated: 04.10.2016 at 15:05