Bring Concurrency to MicroProfile

921 views
Skip to first unread message

Emily Jiang

unread,
Jul 11, 2018, 12:16:44 PM7/11/18
to Eclipse MicroProfile
In today's Fault Tolerance call, we talk about the asynchronous reactive aspect of Fault Tolerance. We are working towards to support the following scenario:

@Asynchronous
public CompletionStage getMyService() {


...
}

The natural way to return a CompletionStage is to use CompletableFuture. However, the thread from CompletableFuture is from the default ForkJoinPool, which gives us unmanaged threads. In order to ensure contexts propagation, we need ManagedExecutorService from Concurrency spec.

We could bring in the concurrency spec and add more functionality to the ManagedExecutorService to return a better implementation of CompletionStage. I think this is beneficial to MicroProfile specs, as RestClient has also support the async client. I think mp-reactive is trying to support the similar thing.

We could let concurrency to manage all async issues while the other specs just need to rely on concurrency spec.

Interestingly enough, during my conversation with Adam Bien, Adam expressed his desire of encouraging MicroProfile to bring in the concurrency spec as he uses ManagedExecutorService very frequently.

I think they are some other use cases as well. Please do join in and share your thoughts.


Thanks,
Emily

m.reza.rahman

unread,
Jul 11, 2018, 1:15:36 PM7/11/18
to microp...@googlegroups.com
There is definitely work to be done in Java EE concurrency. It could be the primary vehicle to create CDI versions of previously EJB annotations (including @Asynchronous). In addition, we also need more portable (annotation based) ways of defining concurrency resources.

With regards to completable future, quite honestly I believe the Java SE team dropped the ball on this one. There should have been an SPI that allows for running completable future safely in a managed environment. Short of that, I agree creating a managed version of completable future in Java EE concurrency is the way to go.

Sent via the Samsung Galaxy S7, an AT&T 4G LTE smartphone
--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/516ff9af-84c3-44d4-bc90-121e7d2ec012%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ken Finnigan

unread,
Jul 11, 2018, 1:18:33 PM7/11/18
to Eclipse MicroProfile
It's not a bad idea to include Concurrency spec into MP as part of the base. However, we'd need to ensure that it's inclusion isn't misused in a way that causes large numbers of Threads to be created.

One thing to note, REST Client is able to offer async today without Concurrency spec being present in MP. It's likely that the implementations utilize ManagedExecutorService internally, but it's not necessary at the spec level.

Ken

Nathan Rauh

unread,
Jul 11, 2018, 5:16:18 PM7/11/18
to Eclipse MicroProfile
Regarding the possibility of the Concurrency spec being misused to cause large numbers of thread to be created, I would argue that the already-available Java SE concurrent package currently allows for that sort of misuse, but the EE Concurrency spec could actually offer an improvement here because it provides for the possibility of reusing a core set of managed threads rather than the application creating a bunch of independently operating thread pools of its own.

Alasdair Nottingham

unread,
Jul 11, 2018, 8:55:37 PM7/11/18
to microp...@googlegroups.com
I don’t know how I feel about this. I get the point Emily raises about managed threads being good, but I am not sure how I feel about extending the programming model for micro profile because of an implementation detail of a specification. 

If we think MP apps should directly use concurrency then we should pull it in for sure, but if all we need is a different implementation of CompletionStage isn’t this an implementation detail? Maybe one implementation wants to use the default fork join pool, maybe another wants to use JavaEE concurrency, maybe another has a totally different approach. 

Alasdair Nottingham
--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

Ken Finnigan

unread,
Jul 11, 2018, 10:15:48 PM7/11/18
to Eclipse MicroProfile
Emily,

Maybe it would be beneficial if you can outline the specific use case details where you see the Concurrency spec is necessary.

On reading Alasdair comments and rethinking it, I do see in most cases whether Concurrency spec is necessary is an implementation detail and not something that's required as a base for the specs to build on. Happy to be proven wrong.

Ken

James Roper

unread,
Jul 11, 2018, 11:46:58 PM7/11/18
to MicroProfile
A custom implementation of CompletionStage won't solve the problems.

The reason is, MicroProfile (or Jakarta EE) is not in control of all the CompletionStage's being created. Unless we constrain MicroProfile to never be used with any third party libraries, the moment a user brings in a third party library, eg, a reactive database client, that's going to return whatever CompletionStage it wants to (eg CompletableFuture), and the callbacks to that will either run on the thread that redeems the CompletionStage (which would typically be an IO thread managed by the third party library), the calling thread, or JDK common fork join pool (depending on whether the Async variant of methods is used or not). We of course want MicroProfile to be able to work with third party libraries, so that's not an option.

And, if we did supply our own implementation of CompletionStage for the CompletionStages' that our APIs return, then developers would have a very confusing experience, because whether context was propagated or not would depend on where the CompletionStage came from.

I think the only sane way to deal with this is to firstly educate developers that they need to manage the propagation of context themselves, and secondly provide them with a generic mechanism in CDI - eg, an executor - that they can use to propagate any arbitrary CDI context, so they can supply this to the CompletionStage API to do the context propagation for them. I've tried to talk to CDI people before about offering such APIs for generic propagation of context, but every time I've raised it the answer has been "that's not how CDI is supposed to work". I think it's time to wake up to reality, either CDI is completely incompatible with reactive and asynchronous programming and doing reactive programming requires abandoning the context features of it, or CDI needs to come up to speed and offer APIs for context propagation to threads that are not controlled by the container.

It's also worth having a broader discussion about whether thread local context is something that we want to continue to rely on going forward - it really only works nicely in a thread per request model, once operations have a many to many mapping with threads, it gets very painful, if not practically impossible, to maintain the context.


For more options, visit https://groups.google.com/d/optout.


--
James Roper
Senior Developer, Office of the CTO

Lightbend – Build reactive apps!
Twitter: @jroper

Guillermo González de Agüero

unread,
Jul 12, 2018, 2:32:33 AM7/12/18
to microp...@googlegroups.com
Hi James,

Great explanation. Does https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ContextService.html somewhat cover your idea (provided that it propagates CDI scopes, of course)?


Regards,

Guillermo González de Agüero

Emily Jiang

unread,
Jul 12, 2018, 6:04:40 AM7/12/18
to Eclipse MicroProfile
I am not sure what Rest Client is doing for the CompletionStage. I think it hits the same issue. How does an end user create a CompletionStage in Java EE context? I don't think it is valid thing to say it is implementation detail. At the moment, the only easy way to get an instance of CompletionStage is via CompletableFuture, which is Java SE version as explained by Reza .

e.g. in an end user's code
@Asynchronous
public CompletionStage getMyService() {

//How can a developer create a completionStage for Java EE, as the CompletableFuture does not get thread from managed thread pool, none context will be propagated
..

}

One proposal is to offer a EE version of CompletableFuture and add to Concurrency spec, so that anyone uses MP concurrency to get a useful CompletionStage. I think Nathan has some detailed design to extend ManagedExecutorService and would like to propose to the future Concurrency spec anyway, which might be ideal to bring to MP concurrency first. I don't want to steal his thunder. Nathan, please explain in more details.

Thanks
Emily

Antoine Sabot-Durand

unread,
Jul 12, 2018, 7:38:32 AM7/12/18
to microp...@googlegroups.com
Hi James,

I probably don't see all the requirement for reactive approach but I can give you my spec lead input on CDI contexts. I think the following points may be useful to move the reflexion on context propagation in the right direction.

- CDI built-in contexts (Request Context, Session, etc...) don't propagate. Even Application context doesn't : it is shared across application threads
- While built-in contexts don't propagate nothing in the spec prevent creation of a custom context that can propagates (or is hared across multiple threads)
- Contexts in CDI manage creation and destruction of managed instances so they have to control the way and place where these instance are stored. It's the reason why context propagation can't be managed outside context but should be managed but the context itself
- Instances that may use context should be contextual instances (instantiated and managed by CDI container) or at least non contextual instances (not managed by CDI but having injection honored by CDI). So if you use 3rd party framework you'll have to provide a CDI layer for them if you want to use CDI contexts.

I don't know if CDI context constraints is compatible with a reactive / multi-thread approach, but it should be made by extending it with custom context and portable extensions.

Antoine

 

Nathan Rauh

unread,
Jul 12, 2018, 10:07:41 AM7/12/18
to microp...@googlegroups.com
Here is the writeup of the enhancement for ManagedExecutorService to create a thread context aware CompletionStage that I proposed to the EE Concurrency spec (now under Jakarta EE),

https://github.com/eclipse-ee4j/concurrency-api/issues/40

It was written in terms of the Java SE 8 CompletableFuture interface, but the general proposal is to add methods to the existing ManagedExecutorService interface that correspond to the static methods of CompletableFuture, so accounting for Java SE 9+ would be something like,

CompletableFuture<Void> runAsync(Runnable);
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
<U> CompletableFuture<U> completedFuture(U value);
<U> CompletionStage<U> completedStage(U value);
<U> CompletableFuture<U> failedFuture(Throwable ex);
<U> CompletionStage<U> failedStage(Throwable ex);

I'm uncertain what is meant by some of the suggestions that usage of ManagedExecutorService is an implementation detail.
In many cases, usage of ManagedExecutorService vs alternatives is directly specified within application code.

In JAX-RS, the user specifies a ManagedExecutorService or other ExecutorService via the ClientBuilder,
https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/ClientBuilder.html#executorService-java.util.concurrent.ExecutorService-

because JAX-RS implementation itself constructs the CompletableFuture to be returned to the user, it needs to be aware of the fact that it was supplied a ManagedExecutorService that ought to be backing the CompletableFuture.  This has been identified as a deficiency in the JAX-RS spec, and the proposal that I wrote up above was specifically written to address this -- to give JAX-RS a way of obtaining such a CompletableFuture.

In Emily's MicroProfile fault tolerance proposal, the user obtains and returns a CompletionStage of their own choosing, whether it came from Java SE CompletableFuture or otherwise.  We are proposing that if they want context propagation and use of managed threads, then they should be able to obtain one from a ManagedExecutorService, by reusing the same solution that we are hoping to provide for JAX-RS,

@Asynchronous
public CompletionStage<Integer> computeSomething() {
    return managedExecutorService.supplyAsync(computeInitialValue).thenApplyAsync(...);
}

or if they don't need context propagation and want the default ForkJoinPool,

@Asynchronous
public CompletionStage<Integer> computeSomething() {
    return CompletableFuture.supplyAsync(computeInitialValue).thenApplyAsync(...);
}

I don't see this meaning that MP Fault tolerance has a hard dependency on Concurrency, but rather that Concurrency can be enabled and used in conjunction with MP Fault tolerance.

While it would be an option to wait for Jakarta EE, progress there can be slow, and there could be some value in bringing Concurrency into Microprofile to allow for potential innovation and proof of concept in advance of adoption into Jakarta.






From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/744780aa-320d-45fd-9798-73c204c73931%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Kevin Sutter

unread,
Jul 12, 2018, 11:53:38 AM7/12/18
to Eclipse MicroProfile
Sounds like there are two issues associated with this request (at least two)...

1)  Whether Concurrency should be introduced as an API for application usage?  Or, whether the desired Concurrency usage is an SPI or Implementation Detail?  This is a key distinction and discussion item for including new Java EE specs in the base MicroProfile offering.

2)  Enhancing the Concurrency specification...  It sounds like Concurrency is not sufficient for the intended usage.  Nathan has posted some ideas on what needs to be improved.  Just talking from a Jakarta EE perspective, enhancing the Concurrency specification can not happen for some period of time.  We have to complete Jakarta EE 8 before new or updated specs can be entertained.  And, we need to have a finalized specification process in Eclipse.  I know some of this can happen in parallel, but the end game will be dependent on Jakarta EE processes and schedules.  Thus, having Fault Tolerance be dependent on an update to Concurrency may not be the best game plan...

-- Kevin

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

Richard Monson-Haefel

unread,
Jul 12, 2018, 4:17:33 PM7/12/18
to microp...@googlegroups.com
It is unclear at this point if a Jakarta EE 8/9/n specification can reference a Java EE 8 specification and then define the delta (changes and additions).  If Oracle ends up allowing this and expands that permission to MP then you could create a new Concurrency spec for MP and reference Java EE 8 Concurrency specifying the delta.  When Jakarta EE 9 is ready for development, the Jakarta EE 9 Concurrency project could then adopt the deltas defined by the MP Concurrency spec to re-align them.

However, if Oracle will not allow Java EE 8 specifications to be referenced by Jakarta EE specifications, this will not work. In which case you may have to either wait for Jakarta EE 9 concurrency to be defined or simply create a new concurrency spec for MP that captures the differences without referencing the original Java EE 8 concurrency spec.

To unsubscribe from this group and stop receiving emails from it, send an email to microprofile+unsubscribe@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

Emily Jiang

unread,
Jul 12, 2018, 6:12:42 PM7/12/18
to Eclipse MicroProfile


2)  Enhancing the Concurrency specification...  It sounds like Concurrency is not sufficient for the intended usage.  Nathan has posted some ideas on what needs to be improved.  Just talking from a Jakarta EE perspective, enhancing the Concurrency specification can not happen for some period of time.  We have to complete Jakarta EE 8 before new or updated specs can be entertained.  And, we need to have a finalized specification process in Eclipse.  I know some of this can happen in parallel, but the end game will be dependent on Jakarta EE processes and schedules.  Thus, having Fault Tolerance be dependent on an update to Concurrency may not be the best game plan...

I think we can adopt Java EE concurrency and then add an API on top of it. When Jakarta EE is settled, we can propose the change to Jakarta EE. In this way, MicroProfile is seen to be prototype vehicle. This is not ideal. However waiting may not be a best solution. I know migrating from Java EE to Jakarta EE is moving along. Waiting for next year and then wait for apis (another few months maybe) to be added is not ideal.

It is unclear at this point if a Jakarta EE 8/9/n specification can reference a Java EE 8 specification and then define the delta (changes and additions).  If Oracle ends up allowing this and expands that permission to MP then you could create a new Concurrency spec for MP and reference Java EE 8 Concurrency specifying the delta.  When Jakarta EE 9 is ready for development, the Jakarta EE 9 Concurrency project could then adopt the deltas defined by the MP Concurrency spec to re-align them.

I like your idea. I am not sure why we need Oracle permission. If we come up with MP concurrency by just including Java EE concurrency, we are ok to add any classes as long as we don't use their package names.
 
Emily

James Roper

unread,
Jul 12, 2018, 9:23:35 PM7/12/18
to MicroProfile
On Thu, 12 Jul 2018 at 21:38, 'Antoine Sabot-Durand' via Eclipse MicroProfile <microp...@googlegroups.com> wrote:
Hi James,

I probably don't see all the requirement for reactive approach but I can give you my spec lead input on CDI contexts. I think the following points may be useful to move the reflexion on context propagation in the right direction.

- CDI built-in contexts (Request Context, Session, etc...) don't propagate. Even Application context doesn't : it is shared across application threads

This is a problem as soon as you use reactive programming to handle a request. If I have a JAX RS method like this:

@RequestScoped
private MyRequestScopedComponent requestScopedComponent;

@GET
@Path("/")
public CompletionStage<Response> handleRequest() {
  CompletionStage<QueryResult> resultFuture = myReactiveDatabase.makeQuery();
  return resultFuture.thenApply(result -> {
    return requestScopedComponent.transformToResponse(result);
  });
}

That doesn't work, since the thread that executes the callback passed to resultFuture.thenApply won't have the request context, since that thread is likely to be one of the database drivers IO event loop threads, and therefore won't be able to use the requestScopedComponent. By not allowing request context to be propagated to non container managed threads, it forces all request handling into a single thread per request programming model, which is the opposite of and fundamentally incompatible with reactive programming, where multiple threads are involved in handling a single request.

- While built-in contexts don't propagate nothing in the spec prevent creation of a custom context that can propagates (or is hared across multiple threads)

That's true, but this requires each context to implement their own mechanism, which requires manually using that contexts propagation support each time you want to propagate context. The biggest problem here is that another library that wants to offer reactive features, but doesn't know about all the custom contexts that a user might want propagated, is unable to propagate that context for the user.
 
- Contexts in CDI manage creation and destruction of managed instances so they have to control the way and place where these instance are stored. It's the reason why context propagation can't be managed outside context but should be managed but the context itself

And that's fine, but it doesn't preclude CDI from offering APIs that abstract over how the context is stored, and therefore allow generic, context agnostic propagation.
 
- Instances that may use context should be contextual instances (instantiated and managed by CDI container) or at least non contextual instances (not managed by CDI but having injection honored by CDI). So if you use 3rd party framework you'll have to provide a CDI layer for them if you want to use CDI contexts.

It's not instance that are the problem here, it's what threads interact with those instances. Unlike a thread per request (or operation, eg handling a message) model, in reactive programming, the container does not have control over which threads interact with which instances during which operation. During the lifecycle of a particular context, there may be many threads involved in processing that requires that context.
 

For more options, visit https://groups.google.com/d/optout.

Clement Escoffier

unread,
Jul 13, 2018, 2:15:46 AM7/13/18
to 'Emily Jiang' via Eclipse MicroProfile
Hello,


On 13 Jul 2018, at 03:23, James Roper <ja...@lightbend.com> wrote:

On Thu, 12 Jul 2018 at 21:38, 'Antoine Sabot-Durand' via Eclipse MicroProfile <microp...@googlegroups.com> wrote:
Hi James,

I probably don't see all the requirement for reactive approach but I can give you my spec lead input on CDI contexts. I think the following points may be useful to move the reflexion on context propagation in the right direction.

- CDI built-in contexts (Request Context, Session, etc...) don't propagate. Even Application context doesn't : it is shared across application threads

This is a problem as soon as you use reactive programming to handle a request. If I have a JAX RS method like this:

@RequestScoped
private MyRequestScopedComponent requestScopedComponent;

@GET
@Path("/")
public CompletionStage<Response> handleRequest() {
  CompletionStage<QueryResult> resultFuture = myReactiveDatabase.makeQuery();
  return resultFuture.thenApply(result -> {
    return requestScopedComponent.transformToResponse(result);
  });
}

That doesn't work, since the thread that executes the callback passed to resultFuture.thenApply won't have the request context, since that thread is likely to be one of the database drivers IO event loop threads, and therefore won't be able to use the requestScopedComponent. By not allowing request context to be propagated to non container managed threads, it forces all request handling into a single thread per request programming model, which is the opposite of and fundamentally incompatible with reactive programming, where multiple threads are involved in handling a single request.

About this specific issue, there are solutions. While I must admit they are far from optimal, but we can do something like:

CompletionStage<QueryResult> future = makeQuery();
ContextState states = Context.capture();
future.thenApply(response -> {
    ContextState previousStates = states.install();
    try {
        // …. 
    }finally {
        previousStates.restore();
    }
});

It’s actually what we do for CompletableStage. When using RX, things are hidden - the context propagation happens “automatically”. 



- While built-in contexts don't propagate nothing in the spec prevent creation of a custom context that can propagates (or is hared across multiple threads)

That's true, but this requires each context to implement their own mechanism, which requires manually using that contexts propagation support each time you want to propagate context. The biggest problem here is that another library that wants to offer reactive features, but doesn't know about all the custom contexts that a user might want propagated, is unable to propagate that context for the user.
 
- Contexts in CDI manage creation and destruction of managed instances so they have to control the way and place where these instance are stored. It's the reason why context propagation can't be managed outside context but should be managed but the context itself

And that's fine, but it doesn't preclude CDI from offering APIs that abstract over how the context is stored, and therefore allow generic, context agnostic propagation.

That’s an issue we are hitting too. We implemented as few propagators. Things are not yet settled here, we are still exploring. It may be something to add to a spec at some point.

 
- Instances that may use context should be contextual instances (instantiated and managed by CDI container) or at least non contextual instances (not managed by CDI but having injection honored by CDI). So if you use 3rd party framework you'll have to provide a CDI layer for them if you want to use CDI contexts.

It's not instance that are the problem here, it's what threads interact with those instances. Unlike a thread per request (or operation, eg handling a message) model, in reactive programming, the container does not have control over which threads interact with which instances during which operation. During the lifecycle of a particular context, there may be many threads involved in processing that requires that context.
 
I don't know if CDI context constraints is compatible with a reactive / multi-thread approach, but it should be made by extending it with custom context and portable extensions.

We have to explore the current limits and see what can be done. With the help of Antoine, we may even be able to “slightly" change the spec ;-)

Clement

James Roper

unread,
Jul 13, 2018, 3:28:58 AM7/13/18
to MicroProfile
On Fri, 13 Jul 2018 at 16:15, Clement Escoffier <clement....@gmail.com> wrote:
[snip]
About this specific issue, there are solutions. While I must admit they are far from optimal, but we can do something like:

CompletionStage<QueryResult> future = makeQuery();
ContextState states = Context.capture();
future.thenApply(response -> {
    ContextState previousStates = states.install();
    try {
        // …. 
    }finally {
        previousStates.restore();
    }
});

It’s actually what we do for CompletableStage. When using RX, things are hidden - the context propagation happens “automatically”. 

It's that sort of API that I'd like CDI to offer - but I don't know where you're getting that ContextState API from - it's not in CDI 2.0 as far as I can see? Is it something internal to Weld?

Exactly the same thing could be achieved by offering an API that does something like this:


CompletionStage<QueryResult> future = makeQuery();
future.thenApply(response -> {
        // …. 
}, Context.capture());

Where Context.capture() returns an executor that holds the ContextState, then installs it before running any runnables passed in, and restores the previous states in a finally block.

Clement Escoffier

unread,
Jul 13, 2018, 3:37:10 AM7/13/18
to microp...@googlegroups.com

On 13 Jul 2018, at 09:28, James Roper <ja...@lightbend.com> wrote:

On Fri, 13 Jul 2018 at 16:15, Clement Escoffier <clement....@gmail.com> wrote:
[snip]
About this specific issue, there are solutions. While I must admit they are far from optimal, but we can do something like:

CompletionStage<QueryResult> future = makeQuery();
ContextState states = Context.capture();
future.thenApply(response -> {
    ContextState previousStates = states.install();
    try {
        // …. 
    }finally {
        previousStates.restore();
    }
});

It’s actually what we do for CompletableStage. When using RX, things are hidden - the context propagation happens “automatically”. 

It's that sort of API that I'd like CDI to offer - but I don't know where you're getting that ContextState API from - it's not in CDI 2.0 as far as I can see? Is it something internal to Weld?

No, it’s something we experiment in the Vert.x context. It’s named reactive-contexts (https://github.com/reactiverse/reactive-contexts) [remember, we are bad at naming].


Exactly the same thing could be achieved by offering an API that does something like this:

CompletionStage<QueryResult> future = makeQuery();
future.thenApply(response -> {
        // …. 
}, Context.capture());

Where Context.capture() returns an executor that holds the ContextState, then installs it before running any runnables passed in, and restores the previous states in a finally block.

Yes, that would be very interesting! I don’t think it’s hard to achieve. Now the issue is, as stated above, what’s part of the context. 

BTW, does akka-streams has some built-in propagation support? 

Clement



--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

Ken Finnigan

unread,
Jul 13, 2018, 8:18:02 AM7/13/18
to Eclipse MicroProfile
Maybe MP Reactive could look to introduce a "reactive" Context for CDI that can be propagated?

Ken

Stephane Epardaud

unread,
Jul 13, 2018, 9:36:52 AM7/13/18
to microp...@googlegroups.com
Note that I already have an implementation of Reactive Contexts that works with CDI request scope propagation.

Stephane Epardaud

unread,
Jul 13, 2018, 9:38:35 AM7/13/18
to microp...@googlegroups.com
Note that with Reactive Contexts 1.0.0, which is now used by resteasy, you can wrap CompletionStage instances with Context.wrap to achieve this.

Alasdair Nottingham

unread,
Jul 13, 2018, 10:09:59 AM7/13/18
to microp...@googlegroups.com
Would that allow me to use an @RequestScope annotated bean and have the same instance available to multiple threads processing the same request? I think I would want to be able to do that. 

Alasdair Nottingham

Nathan Rauh

unread,
Jul 13, 2018, 3:34:19 PM7/13/18
to microp...@googlegroups.com
Regarding,


future.thenApply(response -> {
        // …. 
}, Context.capture());

CompletionStage/CompletableFuture doesn't actually have a method of that signature.  If you instead use thenApplyAsync, you can optionally supply an executor as above and that might be what this intended to refer to.  But then the solution doesn't cover the synchronous (in that execution is relative to a prior stage, or to a thread requesting to join/get/and so forth) path at all.
I suppose you could supply a run-on-current-thread executor to thenApplyAsync to get that effect, but it seems like an abuse of the API that would result in misleading code that is difficult to understand.

If the user wants to explicitly specify context propagation with the creation of every stage, it would be better done around the action (Runnable, Function, Supplier, and so forth) such that the full CompletionStage/CompletableFuture API can still apply.  The ContextService from the EE Concurrency spec works for this purpose, but it's not a very elegant or concise solution.  ContextService was intended for very advanced patterns and it seems undesirable to need to repeatedly use it with something so commonplace as completion stages.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/93358C9D-D541-4392-B37A-775600DD1895%40gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Ondro Mihályi

unread,
Jul 14, 2018, 3:55:39 AM7/14/18
to Eclipse MicroProfile
Hi,

I actually like the suggestion with Context.capture(), it might be the simplest and most readable solution. The real problem is that we can't control the thread and its context when a user calls future.thenApply( lambda ), because the lambda can be executed on a thread without any context created by a library or an unexperienced user.

Let's compare solutions that we have until now:

1. states.install() by Clement:

ContextState states = Context.capture();
future.thenApply(response -> {
    ContextState previousStates = states.install();
    try {
        // business logic
    }finally {
        previousStates.restore();
    }
});

2. Context.capture() suggested by James, only if method accepts executor


future.thenApplyAsync(response -> {
        // …. 
}, Context.capture());

3. using ContextService by Nathan (this is very simiilar to 1. - code example by me, it's a pseudo code because ContextService is way more complex to use):

@Inject ContextService contextService;

ContextState state = contextService.capture();

future.thenApply(response -> {
    state.executeWithContext( () -> {
        // business logic
    }
});


4. CF methods in managed executor by Nathan (modified by me):

@Inject ManagedExecutorService managedExecutorService;

managedExecutorService.thenCompose(future)
  .thenApply( lambda )

I think 2. and 4. can be nicely combined, I'm going to detail in another message.

--Ondro

Ondro Mihályi

unread,
Jul 14, 2018, 5:38:28 AM7/14/18
to MicroProfile
Out of the 4 solutions in my previous messages, I think that solution 2. adds the least amount of complexity and boilerplate code on users' side. For cases where more control is needed or a method doesn't accept an executor, an equivalent solution number 5. (similar to solution 4.), using  thenCompose, can be provided, like this:

5. using thenCompose by Ondro (inspired by Nathans solution with managed CF-like methods)

future.thenCompose(Context.withContext())
  .thenApply( businessLogic );

Context.withContext() method would return a Function that would remember the context and establish it when executed by the future.

It's not much longer than the solution 2. I'm posting solution 2 and modified 4 here for an easy comparison:


2. Context.capture() suggested by James

future.thenApplyAsync( businessLogic, Context.capture());


4. non-fluent CF-like methods by Nathan (modified by me):

Context.thenCompose(future)
  .thenApply( lambda )



All 3 solutions are capable of establishing the proper context on the current thread (the executor in 2. doesn't have to spawn a new thread).

However, solution 2. can be designed to wrap either only a single invocation or establish the context for all subsequent invocations. Solutions 4. and 5. can only establish the context for subsequent invocations because it can't establish boundaries around invocations.

Solution 2. doesn't establish the context when a user calls async methods on a CompletableFuture without an executor - they will always be executed on a forkjoin pool. Solution 5. can return a managed CompletableFuture which could do that. However, this isn't bulletproof either because the method thenCompose on Java SE CompletableFuture always creates a new instance of Java SE CompletableFuture, bypassing the managed one and calling async methods on forkjoin pool again. As a result, users would have to avoid using async methods without an executor with both solutions. It also means that thenApply(Context::withContext) can be used instead of thenCompose(Context::withContext), because the CompletionStage returned from thenCompose doesn't propagate. The only way to to propagate a managed CompletionStage is via a static method like in solution 4. (not fluent API), wrapping any completionStage and returning a managed one: Context.thenCompose( future ).thenApplyAsync( lambda ). I don't think it's necessary, using async methods isn't frequent and users should remember to use them with an executor. It also converts CF to CS and users would have to use toCompletableFuture to get CF back, leading to too much boilerplate.

Going into details of solution 5., the withContext method could look like this:

    <T> Function<? super T, ? extends CompletionStage<T>> withContext() {
        Executor executorWithContext = captureContext(); // captures the current context
        return value -> {
            // establishes the context in a thread used by the future
            establishContextForThisThread();
            return ManagedFuture.completedFuture( value, executorWithContext );  // managed future with a default executor
        }
    }





--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microprofile+unsubscribe@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

Ondro Mihályi

unread,
Jul 14, 2018, 5:51:38 AM7/14/18
to MicroProfile
To shortly summarize main differences among all solutions:

Solutions 1. and 3. establish context for arbitrary wrapped code. Solution 2. establishes context for wrapped code only when using async methods that accept executor. Solutions 4. and 5. establish context without boundaries - the context is established for all future invocations on the same thread. Is there a significant problem with any of these approaches?

Solutions 2. and 5. allow writing fluent code. Other solutions require wrapping of business logic into static methods or inject biolerplate code into several places. Do we care?

Solution 5. ensures that users always work with a managed CompletionStage, which establishes the context for all normal and async invocations. None of the other solutions can do that. Is it needed? Is it worth to provide this option even if it's not fluent?

What's your opinion?

Nathan Rauh

unread,
Jul 15, 2018, 3:50:16 PM7/15/18
to microp...@googlegroups.com
Ondro,

Some of the limitations you identified with solution 4 are just due to how you wrote it up.  I didn't intend it to be non-fluent or to force the user to deal with CompletionStage rather than CompletableFuture.  Here is the usage I envisioned,

4.
@Inject ManagedExecutorService managedExecutor;

completableFuture = managedExecutor.supplyAsync(supplier)
    .thenApplyAsync(function1)
    .thenApply(function2)
    ...

Its usage is identical to CompletableFuture because it is an extension of CompletableFuture, which happens to be obtained from a managed executor service (or similar Microprofile API in the absence of EE Concurrency).  There is no boilerplate code at all around propagating context, supplying executors, or trying to preserve usage of the right thread pool.  By obtaining it from a managed executor, all of that is built in so that the user does not need to concern themselves with any of that and can just treat it like any other CompletableFuture instance.   I'm certain this can be achieved because we prototyped it in OpenLiberty back when working on the JAX-RS reactive client, only we didn't enable it because JAX-RS decided to wait for the EE Concurrency update.


In all of these approaches we need to be very cautious about relying on the user to arrange usage of CompletableFuture in creative ways to achieve context propagation.  There are a lot of quirks with how CompletableFutures behave.  Solution 5 suffers from one of them,

5.
future.thenCompose(Context.withContext())
  .thenApply( businessLogic );

The intent above seems to be establishing context in a prior stage and then expecting the subsequent non-async stage to run under that context.  Sometimes, intermittently, it will work that way.  But other times, after the first stage, thenCompose, completes but before it gets a chance to run the dependent (second) stage, another thread will come in and join/get on the second stage, causing the second stage to run, not under the context established by thenCompose, but under whatever context happens to be on the thread that issued the join or get operation.


Regarding solution 3, we should write out exactly what the syntax looks like, given that this solution is already possible with the existing EE Concurrency ContextService,

@Inject ContextService contextService;

@SuppressWarnings("unchecked")
CompletableFuture<Integer> completableFuture = CompletableFuture
    .supplyAsync(contextService.createContextualProxy(supplier, Supplier.class))
    .thenApplyAsync(contextService.createContextualProxy(function1, Function.class))
    .thenApply(contextService.createContextualProxy(function2, Function.class))
    ...





From:        "Ondro Mihályi" <ondrej....@gmail.com>
To:        MicroProfile <microp...@googlegroups.com>
Date:        07/14/2018 04:38 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile
Sent by:        microp...@googlegroups.com




Out of the 4 solutions in my previous messages, I think that solution 2. adds the least amount of complexity and boilerplate code on users' side. For cases where more control is needed or a method doesn't accept an executor, an equivalent solution number 5. (similar to solution 4.), using  thenCompose, can be provided, like this:

5. using thenCompose by Ondro (inspired by Nathans solution with managed CF-like methods)

future.thenCompose(Context.withContext())
  .thenApply( businessLogic );

Context.withContext() method would return a Function that would remember the context and establish it when executed by the future.

It's not much longer than the solution 2. I'm posting solution 2 and modified 4 here for an easy comparison:


2. Context.capture() suggested by James

future.thenApplyAsync( businessLogic, Context.capture());


4. non-fluent CF-like methods by Nathan (modified by me):

Context.thenCompose(future)
  .thenApply( lambda )



All 3 solutions are capable of establishing the proper context on the current thread (the executor in 2. doesn't have to spawn a new thread).

However, solution 2. can be designed to wrap either only a single invocation or establish the context for all subsequent invocations. Solutions 4. and 5. can only establish the context for subsequent invocations because it can't establish boundaries around invocations.

Solution 2. doesn't establish the context when a user calls async methods on a CompletableFuture without an executor - they will always be executed on a forkjoin pool. Solution 5. can return a managed CompletableFuture which could do that. However, this isn't bulletproof either because the method thenCompose on Java SE CompletableFuture always creates a new instance of Java SE CompletableFuture, bypassing the managed one and calling async methods on forkjoin pool again. As a result, users would have to avoid using async methods without an executor with both solutions. It also means that thenApply(Context::withContext)can be used instead of thenCompose(Context::withContext), because the CompletionStage returned from thenCompose doesn't propagate. The only way to to propagate a managed CompletionStage is via a static method like in solution 4. (not fluent API), wrapping any completionStage and returning a managed one: Context.thenCompose( future ).thenApplyAsync( lambda ). I don't think it's necessary, using async methods isn't frequent and users should remember to use them with an executor. It also converts CF to CS and users would have to use toCompletableFuture to get CF back, leading to too much boilerplate.

.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/733a7b18-cf08-46a2-894e-70a9cca7bdfc%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CACZTZYUx-WUDib4iKHWvTTreRB_aKFHTx3PwVKNehoUXruDLGg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


James Roper

unread,
Jul 16, 2018, 6:27:10 AM7/16/18
to MicroProfile
On Fri, 13 Jul 2018 at 22:18, Ken Finnigan <k...@kenfinnigan.me> wrote:
Maybe MP Reactive could look to introduce a "reactive" Context for CDI that can be propagated?

There's been a lot of discussion about this, and it is something that we were planning to do. However, the more I think about it, the less useful I think it is.

Reactive isn't a context. There's no lifecycle for "reactive". There's no state you might want to attach to "reactive". Reactive is just a model for programming, it's not a context.

In contrast, let's say you have a JSON Web Token that you've injected into your @RequestScoped REST endpoint as described here:


If, during some thenApply callback on a CompletionStage in the handling of a request, you need to access that token - a reactive context is of no use to you, what you need is the request context so that you can access that JWT, which lives in the request context. So you need your callbacks, which are all conceptually doing work for the request context - that is to say, the are doing work to produce a response to the request - to have the request context available to them. A reactive context does nothing to help us because conceptually, there is no reactive scope. A request starts, and ends, and has state like JWT tokens etc associated with it, that's the request scope. Reactive programming wants to work to help with the request scope, it doesn't exist in isolation doing stuff for itself, it works for requests, for sessions, to process messages, etc etc. It needs to interact with the built in scopes, there's not some reactive use case that it serves and serves that alone that would make sense to define a context for, it serves requests etc.


For more options, visit https://groups.google.com/d/optout.

Ondro Mihályi

unread,
Jul 16, 2018, 6:39:18 AM7/16/18
to MicroProfile
Hi Nathan,

All the solutions referred to the problem of receiving a general CS/CF where you can't assume that it's managed. James raised the concern about propagating the context for general (unmanaged) stages returned from a third-party library and I addressed it. The 4. in my list is adapted to that, that's why it's non-fluent. I agree that if we only wanted to create a new managed CS, the API can be simple and fluent.


Ad. another thread will come in and join/get:

You're right. The solution 5 isn't valid because it's not guaranteed if the chained method runs on the thread that completes the future or on the thread that adds callbacks. If a future is completed before ading callbacks, callbacks are executed on the current thread without a proper context. I take the solution 5 back, please ignore it. Solution 4 is valid because it creates a managed CF which can have full control over context propagation.


Ad. concurrency utilities and why I didn't use its API for solution 5. (and I used it for solution 4. only because I wanted to copy as much of your original code as possible):

Concurrency utilities is very complicated API to use, doesn't work well with CDI (only via @Resource), provides a fairly complex API with a lot of boilerplate for creating thread factories and capturing context, isn't ready for Java 8.

Therefore I would like to create a simpler concurrency API based on plain CDI (and possibly plain Java SE as a fallback) that takes advantage of Java 8 and doesn't require concurrency utilities from Java EE. They may be used underneath to implement the MP API but not required.

Something like:

@Inject ExecutorService executor; // no ManagedExecutorService, using qualifiers instead of @Resource to inject various executors
@Inject ThreadContext context; // instead of ContextService from Conc. utils

And then methods in ThreadContext:
  • CompletableFuture supplyAsync(Supplier)  // to create a managed future
  • CompletableFuture thenCompose(CompletionStage) // to convert a generic stage to a managed future (solution 4)
  • <T> T withCurrentContext(T), e.g. Supplier withCurrentContext(Supplier) // to create a contextual proxy for a supplied lambda (solution 3, similar also to 1), can be used with and thenXXX methods of CS, like: CS.thenApply( context.withCurrentContext( lambda ))
  • Executor captureExecutor() // this is a syntactic sugar for the previous method specifically to be used in async CS methods (solution 2)
--Ondro

Ondro Mihályi

unread,
Jul 16, 2018, 6:50:17 AM7/16/18
to MicroProfile
I agree here with James - the @RequestScope is flawed even if used with async API in Java EE. The CDI spec specifies that the request scope is completed when servlet method returns. But async servlet API and JAX-RS async endpoints don't complete the request when the methods return. They complete the request when the appropriate method on AsyncContext or AsyncResponse. If the method is called after the servlet/resource method returns, the CDI Request scope is completed but the request is still being processed.

I would like to see CDI spec enhanced to take into account that requests can be completed asynchronously with Servlet and JAX-RS APIs. The request scope shouldn't be completed immediately when a method returns but when the request is completed. For synch processing it's the same moment but for async it's completely different.

If we fix the request scope for async request processing so that it's not completed before the request is completed, then there's no problem when combining request processing with a reactive pipeline, except passing the request context among threads which we  discuss in this email thread already.

--Ondro

To unsubscribe from this group and stop receiving emails from it, send an email to microprofile+unsubscribe@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/107fe66b-0bf6-40ee-bf03-7b1dc9884914%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
James Roper
Senior Developer, Office of the CTO

Lightbend – Build reactive apps!
Twitter: @jroper

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microprofile+unsubscribe@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

Stephane Epardaud

unread,
Jul 16, 2018, 10:33:46 AM7/16/18
to microp...@googlegroups.com
Right, when we run CDI/JAX-RS on Vert.x, we use Reactive Contexts to propagate the request context on new threads or callbacks/pipelines, and we do this to defer closing the CDI context if we're async:

@Override
public void aroundRequest(HttpRequest req, RunnableWithException<IOException> continuation) throws IOException {
        BoundRequestContext cdiContext = CDI.current().select(BoundRequestContext.class).get();
        Map<String,Object> contextMap = new HashMap<String,Object>();
        cdiContext.associate(contextMap);
        cdiContext.activate();
        try {
        // that context is propagated with Reactive Contexts
        continuation.run();
        }finally {
    if(req.getAsyncContext().isSuspended()) {
    req.getAsyncContext().getAsyncResponse().register((CompletionCallback)(t) -> {
        cdiContext.invalidate();
        cdiContext.deactivate();
        cdiContext.dissociate(contextMap);
    });
    }else {
    cdiContext.invalidate();
    cdiContext.deactivate();
    cdiContext.dissociate(contextMap);
    }
        }
}




--
James Roper
Senior Developer, Office of the CTO

Lightbend – Build reactive apps!
Twitter: @jroper

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microprofile...@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Nathan Rauh

unread,
Jul 16, 2018, 11:13:00 AM7/16/18
to microp...@googlegroups.com
Ondro,

+1 to supporting @Inject

I don't at all agree that EE Concurrency is a complicated API.  It does provide a couple of interfaces for advanced usage (ContextService/ManagedThreadFactory), but most users will only ever use the core ManagedExecutorService, which is literally a subinterface of ExecutorService that adds no additional methods, with a default instance provided out of the box.  It's common to inject it with a single line of code and just use the familiar Java SE ExecutorService API on it.  Hopefully what you were referring to as complicated is the ContextService, which doesn't deal with generic types very well.  This happens because it tries to be a generic way of contextualizing any interface.  Your withCurrentContext method gets around this by allowing any instance of any class to be contextualized.  That may be going too far.  An alternative is providing withCurrentContext signatures for the specific types that are of interest to CompletableFuture/ExecutorService,

    <T> Supplier<T> withCurrentContext(Supplier<T> supplier);
    <T, R> Function<T, R> withCurrentContext(Function<T, R> function);
    <T, U, R> BiFunction<T, U, R> withCurrentContext(BiFunction<T, U, R> function);
    <T> Consumer<T> withCurrentContext(Consumer<T> consumer);
    <T, U> BiConsumer<T, U> withCurrentContext(BiConsumer<T, U> consumer);
    <T> Callable<T> withCurrentContext(Callable<T> action);
    Runnable withCurrentContext(Runnable action);

By proposing to inject ThreadContext and ExecutorService independently, it looks like you are wanting to separate the concepts of thread context propagation from container provided/managed executors.  There is certainly some value in that, such as avoiding the penalty of thread context catpure/propagation in paths where it isn't necessary.  This equates to a ManagedExecutorService that is configured to propagate no context, and then in the specific cases where thread context is needed, the ContextService/ThreadContext can be used to contextualize specific tasks/actions.  I'm fine with a model like that.

Methods such as supplyAsync/runAsync and so forth do not belong on ThreadContext.  Those are methods that submit actions for asynchronous execution. They belong on an executor.  If we need to avoid reliance on modifications to the ManagedExecutorService API due to it being in Java EE, I'd propose that we introduce a different interface for Microprofile that inherits from Java SE ExecutorService and has the methods we want.  This would remain fully compatible for Jakarata EE Concurrency to merge into ManagedExecutorService at some future point, after which implementations could conveniently implement both interfaces.  ThreadContext methods could similarly be merged into ContextService in the future, again with implementations conveniently being both.

@Inject ManagedExecutor executor; // extends Java SE ExecutorService
@Inject ThreadContext threadContext;

ThreadContext methods are listed previously above.

ManagedExecutor (or whatever we call it) should have these methods to create CompletableFuture instances that are managed,
CompletableFuture<Void> runAsync(Runnable);
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
<U> CompletableFuture<U> completedFuture(U value);
<U> CompletionStage<U> completedStage(U value);
<U> CompletableFuture<U> failedFuture(Throwable ex);
<U> CompletionStage<U> failedStage(Throwable ex);

Regarding a way to convert a generic stage to a managed CompletableFuture, we could also include composedFuture/composedStage methods.
Alternately could be done without any additional API via,
executor.completedFuture(unused).thenCombine(completableFuture, (unused, cf) -> cf);

We should not include a captureExecutor method.  That pattern misuses the executor parameter and should not be encouraged when we already have ThreadContext methods providing a complete solution.





From:        "Ondro Mihályi" <ondrej....@gmail.com>
To:        MicroProfile <microp...@googlegroups.com>
Date:        07/16/2018 05:39 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile
Sent by:        microp...@googlegroups.com




Hi Nathan,

All the solutions referred to the problem of receiving a general CS/CF where you can't assume that it's managed. James raised the concern about propagating the context for general (unmanaged) stages returned from a third-party library and I addressed it. The 4. in my list is adapted to that, that's why it's non-fluent. I agree that if we only wanted to create a new managed CS, the API can be simple and fluent.


Ad. another thread will come in and join/get:

You're right. The solution 5 isn't valid because it's not guaranteed if the chained method runs on the thread that completes the future or on the thread that adds callbacks. If a future is completed before ading callbacks, callbacks are executed on the current thread without a proper context. I take the solution 5 back, please ignore it. Solution 4 is valid because it creates a managed CF which can have full control over context propagation.


Ad. concurrency utilities and why I didn't use its API for solution 5. (and I used it for solution 4. only because I wanted to copy as much of your original code as possible):

Concurrency utilities is very complicated API to use, doesn't work well with CDI (only via @Resource), provides a fairly complex API with a lot of boilerplate for creating thread factories and capturing context, isn't ready for Java 8.

Therefore I would like to create a simpler concurrency API based on plain CDI (and possibly plain Java SE as a fallback) that takes advantage of Java 8 and doesn't require concurrency utilities from Java EE. They may be used underneath to implement the MP API but not required.

Something like:

@Inject ExecutorService executor; // no ManagedExecutorService, using qualifiers instead of @Resource to inject various executors
@Inject ThreadContext context; // instead of ContextService from Conc. utils

And then methods in ThreadContext:
  • CompletableFuture supplyAsync(Supplier)  // to create a managed future
  • CompletableFuture thenCompose(CompletionStage)// to convert a generic stage to a managed future (solution 4)

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CACZTZYWNTiY3PT5Dv22rBD3Y2Ra1UkamiwuCR82-ARNoBZCKGg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Ondro Mihályi

unread,
Jul 16, 2018, 7:31:33 PM7/16/18
to MicroProfile
Hi Nathan,

Great points!

I completely agree with all what you wrote, you understood me very well. Would you have time to compile all these suggestions into a proposal? You may start in your own repo and post a link to it, later we can create an MP repo and pull request from your repo. Even better, to allow commenting on your code, you could put the code into a branch in your repo and create a PR to the master branch, it would allow commenting the PR even before an MP repo is created.

--Ondro

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microprofile+unsubscribe@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

James Roper

unread,
Jul 16, 2018, 8:27:29 PM7/16/18
to MicroProfile
Hi Nathan,

The problem with the current ContextService is that it's interaction with CDI is unspecified. For example, here's the implementation in TomEE:


You can see propagation of the built in CDI contexts was once implemented, but has been commented out. And I'm guessing this passes the Java EE TCK? So clearly the spec does not require ContextService to propagate CDI contexts, it only requires propagation of the EJB transaction and other EJB specific context.

Furthermore, CDI offers no mechanism to propagate custom contexts, a container can only propagate built in contexts. Reactive programming is an orthogonal concern to contexts - there will be use cases for asynchronous handling in all contexts. What we need is a mechanism so that the user doesn't have to manually propagate contexts using each built in and custom contexts propitiatory propagation API, we need one API that can do them all at once, and preferably in a way that needs no knowledge of what contexts are being used, so that third party libraries can invoke asynchronous callbacks with the right context available without needing knowledge of the contexts.

What I'd like to see is a method on Context itself for capturing the an active context, and then running it. This is the base building block mechanism needed for then implementing higher level APIs that provide executors and the like.

Regards,

James

.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit


--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microprofile...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--

Guillermo González de Agüero

unread,
Jul 17, 2018, 2:27:30 AM7/17/18
to microp...@googlegroups.com, Reza Rahman
Hi,

Regarding CDI contexts and concurrency utilities, there was some discussion about it on 2016. See this thread: http://lists.jboss.org/pipermail/cdi-dev/2016-March/007821.html


Regards,

Guillermo González de Agüero

Stephane Epardaud

unread,
Jul 17, 2018, 4:01:38 AM7/17/18
to microp...@googlegroups.com
Yeah, CDI context propagation was hard to make work. As an example of what needed to be done for the pluggable CDI context propagator, this had some reflection: https://github.com/reactiverse/reactive-contexts/blob/db425392c10e9706d830ee5661f53248757f16b3/providers-weld/src/main/java/fr/epardaud/reactivecontexts/providers/weld/WeldContextProvider.java and we started a discussion with the Weld team at the time to make this more accessible.

Otherwise, what we've learned is that the context propagation API needs to decouple two things:

- context providers (SPI to declare that your lib has a context, and make it available/settable: Weld, RESTEasy, etc…)
- context propagators (SPI to declare that your lib requires context and can handle it automatically, and use Context.capture/restore accordingly: RxJava 1, 2…)

Other use-cases have to do context propagation manually, via Context.wrap (for those types supported, such as CompletionStage, Runnable, etc…) or via Context.capture/restore.

Once this is all set up, it becomes trivial to propagate contexts, automatically (RxJava) or manually (CompletionStage), no matter how many contexts (since that is hidden).


For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Emily Jiang

unread,
Jul 17, 2018, 6:59:39 AM7/17/18
to Eclipse MicroProfile
I have finally caught up with the discussions. +1 on the prototype. I suggest to use sandbox as the repo to add proposal and spec.
+1 on your suggestion, Nathan!

Emily
To unsubscribe from this group and all its topics, send an email to microprofile...@googlegroups.com.

Emily Jiang

unread,
Jul 17, 2018, 7:07:58 AM7/17/18
to Eclipse MicroProfile
I would love to see the context propagation happening on the relevant builtin CDI scopes out of box, especially RequestScoped.
Emily

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.



--
Stéphane Épardaud

Stephane Epardaud

unread,
Jul 17, 2018, 7:16:24 AM7/17/18
to microp...@googlegroups.com
This solution works for Request Scope :)

.



--
Stéphane Épardaud

For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Alasdair Nottingham

unread,
Jul 17, 2018, 8:42:27 AM7/17/18
to microp...@googlegroups.com
I’d also like to see support for arbitrary contexts, but I’m guessing that would require a CDI update?

Stephane Epardaud

unread,
Jul 17, 2018, 8:54:02 AM7/17/18
to microp...@googlegroups.com
Until CDI can be updated to account for this, exploration can be done in Weld and other implementations to support this.


For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Nathan Rauh

unread,
Jul 17, 2018, 10:35:36 AM7/17/18
to microp...@googlegroups.com
Sure thing, I'll get a subfolder for concurrency created in the sandbox repo with the proposed interfaces.

I also agree with the other discussion around putting some standards out there for context providers.  I think EE Concurrency wrongly assumed that all context would be provided internally by single monolithic implementation of all specs together that could always use internals for capturing/propagating it.  A thread context provider SPI would be a welcome addition.  





From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>
To:        Eclipse MicroProfile <microp...@googlegroups.com>
Date:        07/17/2018 06:00 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile




I have finally caught up with the discussions. +1 on the prototype. I suggest to use sandboxas the repo to add proposal and spec.

.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/CACZTZYWNTiY3PT5Dv22rBD3Y2Ra1UkamiwuCR82-ARNoBZCKGg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/OF728F5090.D0609F53-ON002582CC.0049F96D-862582CC.00536995%40notes.na.collabserv.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/462bb2b1-e8c5-4f05-91b7-27b2c9b27f5c%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Emily Jiang

unread,
Jul 17, 2018, 5:27:56 PM7/17/18
to Eclipse MicroProfile
Thanks Nathan!

Alasdair: I’d also like to see support for arbitrary contexts, but I’m guessing that would require a CDI update?

I was going to raise a Jira for this. After a quick search, I found this one already being raised by Romain two years ago. Today, during reactive hangout, I talked with Antoine. I suggested in the next version of CDI, we should investigate this jira and try to fix it. For now, I think we should experiment the workaround provided by Stepane.

Feel free to add your comments on this jira!
Thanks
Emily

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit


--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/OF728F5090.D0609F53-ON002582CC.0049F96D-862582CC.00536995%40notes.na.collabserv.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

Nathan Rauh

unread,
Jul 17, 2018, 5:35:13 PM7/17/18
to microp...@googlegroups.com
Proposed MicroProfile Concurrency interfaces for ManagedExecutor and ThreadContext have been merged into the sandbox here,

https://github.com/eclipse/microprofile-sandbox/tree/master/proposals/concurrency/microprofile-concurrency-api/src/main/java/org/eclipse/microprofile/concurrent





From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>
To:        Eclipse MicroProfile <microp...@googlegroups.com>
Date:        07/17/2018 04:28 PM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile




Thanks Nathan!

Alasdair: I’d also like to see support for arbitrary contexts, but I’m guessing that would require a CDI update?

I was going to raise a Jira for this. After a quick search, I found this onealready being raised by Romain two years ago. Today, during reactive hangout, I talked with Antoine. I suggested in the next version of CDI, we should investigate this jira and try to fix it. For now, I think we should experiment the workaround provided by Stepane.

.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/CACZTZYWNTiY3PT5Dv22rBD3Y2Ra1UkamiwuCR82-ARNoBZCKGg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/OF728F5090.D0609F53-ON002582CC.0049F96D-862582CC.00536995%40notes.na.collabserv.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com

.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/462bb2b1-e8c5-4f05-91b7-27b2c9b27f5c%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit

https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/52cc6aac-7efd-4da0-a30f-bbc88d8fa226%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Nathan Rauh

unread,
Jul 24, 2018, 11:30:39 AM7/24/18
to microp...@googlegroups.com
I finally got around to adding a readme for the Concurrency spec proposal, (https://github.com/eclipse/microprofile-sandbox/blob/master/proposals/concurrency/README.adoc), and in doing so, the question came up of whether/how to allow instances other than the default.  The easiest answer would be to leave this detail to the eventual Jakarta EE spec, and for now only allow the default instance.  Otherwise, the defining of multiple instances implies not just a way to configure, but standardizing what is configurable, and that might be difficult to agree on.  I at least wanted to bring the topic up, in case there is interest/agreement on it.  One thing to emphasize here is that managed executors should not be assumed to be individual thread pools of their own, so rather than having maximum pool size, configured constraints ought to be in terms of maximum async stages that can be concurrently running, or a limit on the number of stages that can be queued up for async execution and so forth.  Or specifying which thread context types to capture & propagate.   Options that come to mind for how to specify configuration:
@Inject @ManagedExecutorConfig(maxAsync=5, maxQueued=20) ManagedExecutor executor;
or have a ManagedExecutorBuilder for programmatic use in combination with CDI @Produces
I'm sure there are others, but wanted to give a few examples here.

The discussion about a thread context provider SPI dropped off, possibly because its timing coincided with the other discussion.  We have a decent set of generic interfaces for that which we use in the Open Liberty EE Concurrency implementation, and I'll see if I can piece an idea together based on that and see if having an actual example generates an further discussion in that area.





From:        Nathan Rauh/Rochester/IBM
To:        microp...@googlegroups.com
Date:        07/17/2018 04:35 PM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile



Proposed MicroProfile Concurrency interfaces for ManagedExecutor and ThreadContext have been merged into the sandbox here,

https://github.com/eclipse/microprofile-sandbox/tree/master/proposals/concurrency/microprofile-concurrency-api/src/main/java/org/eclipse/microprofile/concurrent





From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>
To:        Eclipse MicroProfile <microp...@googlegroups.com>
Date:        07/17/2018 04:28 PM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile




Thanks Nathan!

Alasdair: I’d also like to see support for arbitrary contexts, but I’m guessing that would require a CDI update?

I was going to raise a Jira for this. After a quick search, I found this onealready being raised by Romain two years ago. Today, during reactive hangout, I talked with Antoine. I suggested in the next version of CDI, we should investigate this jira and try to fix it. For now, I think we should experiment the workaround provided by Stepane.

.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/CACZTZYWNTiY3PT5Dv22rBD3Y2Ra1UkamiwuCR82-ARNoBZCKGg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/OF728F5090.D0609F53-ON002582CC.0049F96D-862582CC.00536995%40notes.na.collabserv.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com

.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/462bb2b1-e8c5-4f05-91b7-27b2c9b27f5c%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit

https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/52cc6aac-7efd-4da0-a30f-bbc88d8fa226%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Emily Jiang

unread,
Jul 25, 2018, 6:37:57 PM7/25/18
to Eclipse MicroProfile
Thank you Nathan! +1 on the proposal! I think it will meet the requirement for Fault Tolerance going reactive on supporting the return type of CompletionStage when using Asynchronous. We can advise the developers how to create a better-managed CompletionStage using the managed executor service.

Thanks
Emily

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

Nathan Rauh

unread,
Jul 26, 2018, 11:43:59 AM7/26/18
to microp...@googlegroups.com
Here is what I would propose for a thread context provider SPI if we decide to include one,


org.eclipse.microprofile.concurrent.spi.ThreadContextProvider : Interface to be implemented by a third party provider of thread context, allowing the provided type of context to participate in thread context capture & propagation.

methods:
  ThreadContextSnapshot currentContext(Map<String, String> props) : Captures a snapshot of the provided thread context type from the current thread.  The optional properties parameter is provided for compatibility with EE Concurrency spec, which allows for specifying a set of 'execution properties' when capturing thread context.  Third party providers that don't provide execution properties of their own can simply ignore the parameter.
  ThreadContextSnapshot defaultContext(Map<String, String> props) : Returns a default/clean state snapshot of the provided thread context type.  This can be used in cases where the provided type of thread context should not be propagated from the requesting thread or inherited from the thread of execution, in which case it is necessary to establish a default context in its place so that an action does not unintentionally inherit context of the thread that happens to run it.  For example, a security context provider would ensure there is no authenticated user on the thread.  A transaction context provider would ensure that any active transaction is suspended.  And so forth. The optional properties parameter is provided for compatibility with EE Concurrency spec, which allows for specifying a set of 'execution properties' when capturing thread context.  Third party providers that don't provide execution properties of their own can simply ignore the parameter.


org.eclipse.microprofile.concurrent.spi.ThreadContextSnapshot : An immutable snapshot of a particular type of thread context.  The captured context represented within this snapshot can be applied to any number of threads, including concurrently.  Any state that is associated with context once applied to a thread should be kept, not within the snapshot, but within the distinct ActiveThreadContext instance it creates each time it is applied to a thread.

methods:
  ActiveThreadContext begin() : Applies the captured thread context to the current thread and returns a distinct ActiveThreadContext instance to track the context, including representing any state that is associated with it. For each invocation the container makes of this method, it must invoke the corresponding end method on the ActiveThreadContext instance exactly one, such that the previous context is restored on the thread.


org.eclipse.microprofile.concurrent.spi.ActiveThreadContext : Represents the state of thread context that is applied to a particular thread. When the context is no longer needed on the thread, the container must invoke the end method.  The container must invoke the end method exactly once for each ActiveThreadContext instance that it creates.

methods:
  void end() : Invoked by the container to remove the thread context represented by the ActiveThreadContext instance and restore the previous context that was on the thread before the ActiveThreadContext was started on the thread.  Raises IllegalStateException if invoked more than once.

.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/462bb2b1-e8c5-4f05-91b7-27b2c9b27f5c%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/52cc6aac-7efd-4da0-a30f-bbc88d8fa226%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit

https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/00231a2f-8677-4d4f-b5e6-0a0574e02c50%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


James Roper

unread,
Jul 26, 2018, 9:58:07 PM7/26/18
to MicroProfile
Hi Nathan,

This looks semantically in line with the type of thing I've been thinking. I have some questions:

How would you get a hold of a ThreadContextProvider? Would it be injected? What would be the default context for it if no scope annotation appeared on it - would it make sense to inject a Dependent scoped one of these?

Would all contexts be required to provide a ThreadContextProvider, or is it optional? What would happen if a context doesn't provide it but I try to inject/use it?

What if I wanted to propagate multiple contexts (eg, request, session and conversation), would I have to inject all of these? Would there be a way to combine them into one?

Cheers,

James

You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Nathan Rauh

unread,
Jul 27, 2018, 6:21:16 PM7/27/18
to microp...@googlegroups.com
James - excellent question.  I'll start by pointing out this is for the SPI, so it isn't used directly by applications.  For application usage we have the ThreadContext API from the earlier discussion.  The SPI proposed here is what allows third party providers of thread context to be made available in a standard way such that the ThreadContext API can be implemented to include them.  With those clarifications in place, I'll answer the questions, referencing both the SPI as well as the API where appropriate.


> How would you get a hold of a ThreadContextProvider?
I neglected to mention this part, but it's an important detail.  We could use the standard ServiceLoader mechanism, in which libraries that are providers of thread context include a file named META-INF/services/org.eclipse.microprofile.concurrent.spi.ThreadContextProvider
where the content of the file is the name of the ThreadContextProvider implementation class.
The ThreadContext implementation is then able to do ServiceLoader.load(ThreadContextProvider.class), the result of which can be iterated to obtain all registered ThreadContextProvider instances.

Note that the application doesn't directly use ThreadContextProvider.
Indirectly, it uses
@Inject ThreadContext threadContext;
or
@Inject ManagedExecutor executor;


> Would all contexts be required to provide a ThreadContextProvider, or is it optional? What would happen if a context doesn't provide it but I try to inject/use it?
To answer the second part of the question first, a context type that neglects to provide a ThreadContextProvider wouldn't be included when ThreadContext or ManagedExecutor captures and propagates thread context.  You raise a good point about whether or not to require thread context types to provide ThreadContextProviders.  I think this may be a situation where, except for a core set, we defer the decision on a case-by-case basis to the specs that define each new type of thread context while saying that it is "strongly recommended" to do so.  EE Concurrency requires at least the following: application namespace, security, suspended transaction.  We would have these same core requirements for compatibility (to the extent that such features are even available), and I think we also want to have a requirement for CDI to provide a ThreadContextProvider.  I'm curious what other opinions are here, but at a minimum we do need to clarity (whether at the per-spec level, or within the concurrency spec itself, or in both) so that there is a guaranteed reliable behavior for each type of thread context that an application wants to use.


> What if I wanted to propagate multiple contexts (eg, request, session and conversation), would I have to inject all of these? Would there be a way to combine them into one?
You only inject ThreadContext or ManagedExecutor.  But I think it is worthwhile considering how/whether you should be able to do so in a way that more granularly indicates which specific thread context types you want propagated, and what that level of granularity should be.  If we provide granularity at the ThreadContextProvider level, then we need a spec-defined identifier for the ThreadContextProvider to advertise the name of the type it provides, as well as for the application to indicate which types it wants.  We could add a method to ThreadContextProvider called getThreadContextType, returning String, for this.  The ThreadContextProvider for CDI would return a value of "CDI", allowing the application to do something like,
@Inject @ThreadContextConfig("CDI")
ThreadContext threadContext;
or
@Inject @ManagedExecutorConfig(context = "CDI", ...)
ManagedExecutor executor;
With granularity comes other complexity, such as what if one context requires another. For example, CDI contexts may need to know the application.  So we would also need a ThreadContextProvider method getPrerequisites() to ensure that the application metadata/namespace context is also propagated to the thread when the CDI context is propagated.  We might actually need the prerequisite information regardless, just establish ordering in which context is applied, so that CDI's ThreadContextSnapshot.begin method can rely on being able to access the application metadata/namespace context if it needs to.
You also raised the possibility of even further granularity within a single ThreadContextProvider.  For this we would need a couple of methods,
getThreadContextType returns String, for example, "CDI"
getThreadContextSubTypes: returns String[], for example { "request", "session", ... }
and the currentContextMethod would need an additional argument to accept the desired subtypes.
To avoid conflicts, maybe the user would specify as, @Inject ThreadContextConfig({ "CDI.request", "CDI.session", ... }) ?
This is all easily doable within a thread context provider SPI.  It's more a question of, first, whether subtypes are doable from a CDI perspective, and second, if having context subtypes is even desirable.  My own opinion here is that any granularity beyond the level of the ThreadContextProvider's main context type (CDI, Security, ...) is probably not worthwhile.  I would be curious of others' opinions here.  

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CABY0rKP2E4wiRUrZxgTpRSZcL0rNsqS-F%2BpfXTWLAVrzBvx_XQ%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Reza Rahman

unread,
Aug 1, 2018, 10:34:03 PM8/1/18
to Eclipse MicroProfile
I agree with you. I've suggested the concurrency API be extended to cover CDI in general. I am really not sure how that got basically missed in Java EE 7 and of course not addressed at all in Java EE 8.

On Thursday, July 12, 2018 at 2:32:33 AM UTC-4, Guillermo González de Agüero wrote:
Hi James,

Great explanation. Does https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ContextService.html somewhat cover your idea (provided that it propagates CDI scopes, of course)?


Regards,

Guillermo González de Agüero

El jue., 12 jul. 2018 a las 5:46, James Roper (<ja...@lightbend.com>) escribió:
A custom implementation of CompletionStage won't solve the problems.

The reason is, MicroProfile (or Jakarta EE) is not in control of all the CompletionStage's being created. Unless we constrain MicroProfile to never be used with any third party libraries, the moment a user brings in a third party library, eg, a reactive database client, that's going to return whatever CompletionStage it wants to (eg CompletableFuture), and the callbacks to that will either run on the thread that redeems the CompletionStage (which would typically be an IO thread managed by the third party library), the calling thread, or JDK common fork join pool (depending on whether the Async variant of methods is used or not). We of course want MicroProfile to be able to work with third party libraries, so that's not an option.

And, if we did supply our own implementation of CompletionStage for the CompletionStages' that our APIs return, then developers would have a very confusing experience, because whether context was propagated or not would depend on where the CompletionStage came from.

I think the only sane way to deal with this is to firstly educate developers that they need to manage the propagation of context themselves, and secondly provide them with a generic mechanism in CDI - eg, an executor - that they can use to propagate any arbitrary CDI context, so they can supply this to the CompletionStage API to do the context propagation for them. I've tried to talk to CDI people before about offering such APIs for generic propagation of context, but every time I've raised it the answer has been "that's not how CDI is supposed to work". I think it's time to wake up to reality, either CDI is completely incompatible with reactive and asynchronous programming and doing reactive programming requires abandoning the context features of it, or CDI needs to come up to speed and offer APIs for context propagation to threads that are not controlled by the container.

It's also worth having a broader discussion about whether thread local context is something that we want to continue to rely on going forward - it really only works nicely in a thread per request model, once operations have a many to many mapping with threads, it gets very painful, if not practically impossible, to maintain the context.

On Thu, 12 Jul 2018 at 12:15, Ken Finnigan <k...@kenfinnigan.me> wrote:
Emily,

Maybe it would be beneficial if you can outline the specific use case details where you see the Concurrency spec is necessary.

On reading Alasdair comments and rethinking it, I do see in most cases whether Concurrency spec is necessary is an implementation detail and not something that's required as a base for the specs to build on. Happy to be proven wrong.

Ken

On Wednesday, July 11, 2018 at 8:55:37 PM UTC-4, Alasdair Nottingham wrote:
I don’t know how I feel about this. I get the point Emily raises about managed threads being good, but I am not sure how I feel about extending the programming model for micro profile because of an implementation detail of a specification. 

If we think MP apps should directly use concurrency then we should pull it in for sure, but if all we need is a different implementation of CompletionStage isn’t this an implementation detail? Maybe one implementation wants to use the default fork join pool, maybe another wants to use JavaEE concurrency, maybe another has a totally different approach. 

Alasdair Nottingham

On Jul 11, 2018, at 5:16 PM, Nathan Rauh <natha...@us.ibm.com> wrote:

Regarding the possibility of the Concurrency spec being misused to cause large numbers of thread to be created, I would argue that the already-available Java SE concurrent package currently allows for that sort of misuse, but the EE Concurrency spec could actually offer an improvement here because it provides for the possibility of reusing a core set of managed threads rather than the application creating a bunch of independently operating thread pools of its own.

On Wednesday, July 11, 2018 at 12:18:33 PM UTC-5, Ken Finnigan wrote:
It's not a bad idea to include Concurrency spec into MP as part of the base. However, we'd need to ensure that it's inclusion isn't misused in a way that causes large numbers of Threads to be created.

One thing to note, REST Client is able to offer async today without Concurrency spec being present in MP. It's likely that the implementations utilize ManagedExecutorService internally, but it's not necessary at the spec level.

Ken

On Wednesday, July 11, 2018 at 12:16:44 PM UTC-4, Emily Jiang wrote:
In today's Fault Tolerance call, we talk about the asynchronous reactive aspect of Fault Tolerance. We are working towards to support the following scenario:

@Asynchronous
public CompletionStage getMyService() {


...
}

The natural way to return a CompletionStage is to use CompletableFuture. However, the thread from CompletableFuture is from the default ForkJoinPool, which gives us unmanaged threads. In order to ensure contexts propagation, we need ManagedExecutorService from Concurrency spec.

We could bring in the concurrency spec and add more functionality to the ManagedExecutorService to return a better implementation of CompletionStage. I think this is beneficial to MicroProfile specs, as RestClient has also support the async client. I think mp-reactive is trying to support the similar thing.

We could let concurrency to manage all async issues while the other specs just need to rely on concurrency spec.

Interestingly enough, during my conversation with Adam Bien, Adam expressed his desire of encouraging MicroProfile to bring in the concurrency spec as he uses ManagedExecutorService very frequently.

I think they are some other use cases as well. Please do join in and share your thoughts.


Thanks,
Emily

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
James Roper
Senior Developer, Office of the CTO

Lightbend – Build reactive apps!
Twitter: @jroper

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.

Reza Rahman

unread,
Aug 1, 2018, 10:38:48 PM8/1/18
to Eclipse MicroProfile
This looks like a solid proposal (short of asking the JDK folks for an SPI).

On Thursday, July 12, 2018 at 10:07:41 AM UTC-4, Nathan Rauh wrote:
Here is the writeup of the enhancement for ManagedExecutorService to create a thread context aware CompletionStage that I proposed to the EE Concurrency spec (now under Jakarta EE),

https://github.com/eclipse-ee4j/concurrency-api/issues/40

It was written in terms of the Java SE 8 CompletableFuture interface, but the general proposal is to add methods to the existing ManagedExecutorService interface that correspond to the static methods of CompletableFuture, so accounting for Java SE 9+ would be something like,


CompletableFuture<Void> runAsync(Runnable);
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
<U> CompletableFuture<U> completedFuture(U value);
<U> CompletionStage<U> completedStage(U value);
<U> CompletableFuture<U> failedFuture(Throwable ex);
<U> CompletionStage<U> failedStage(Throwable ex);

I'm uncertain what is meant by some of the suggestions that usage of ManagedExecutorService is an implementation detail.
In many cases, usage of ManagedExecutorService vs alternatives is directly specified within application code.

In JAX-RS, the user specifies a ManagedExecutorService or other ExecutorService via the ClientBuilder,
https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/ClientBuilder.html#executorService-java.util.concurrent.ExecutorService-

because JAX-RS implementation itself constructs the CompletableFuture to be returned to the user, it needs to be aware of the fact that it was supplied a ManagedExecutorService that ought to be backing the CompletableFuture.  This has been identified as a deficiency in the JAX-RS spec, and the proposal that I wrote up above was specifically written to address this -- to give JAX-RS a way of obtaining such a CompletableFuture.

In Emily's MicroProfile fault tolerance proposal, the user obtains and returns a CompletionStage of their own choosing, whether it came from Java SE CompletableFuture or otherwise.  We are proposing that if they want context propagation and use of managed threads, then they should be able to obtain one from a ManagedExecutorService, by reusing the same solution that we are hoping to provide for JAX-RS,

@Asynchronous
public CompletionStage<Integer> computeSomething() {
    return managedExecutorService.supplyAsync(computeInitialValue).thenApplyAsync(...);
}

or if they don't need context propagation and want the default ForkJoinPool,

@Asynchronous
public CompletionStage<Integer> computeSomething() {
    return CompletableFuture.supplyAsync(computeInitialValue).thenApplyAsync(...);
}

I don't see this meaning that MP Fault tolerance has a hard dependency on Concurrency, but rather that Concurrency can be enabled and used in conjunction with MP Fault tolerance.

While it would be an option to wait for Jakarta EE, progress there can be slow, and there could be some value in bringing Concurrency into Microprofile to allow for potential innovation and proof of concept in advance of adoption into Jakarta.






From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>
To:        Eclipse MicroProfile <microp...@googlegroups.com>
Date:        07/12/2018 05:04 AM
Subject:        Re: [microprofile] Re: Bring Concurrency to MicroProfile




I am not sure what Rest Client is doing for the CompletionStage. I think it hits the same issue. How does an end user create a CompletionStage in Java EE context? I don't think it is valid thing to say it is implementation detail. At the moment, the only easy way to get an instance of CompletionStage is via CompletableFuture, which is Java SE version as explained by Reza .

e.g. in an end user's code
@Asynchronous
public CompletionStage getMyService() {

//How can a developer create a completionStage for Java EE, as the CompletableFuture does not get thread from managed thread pool, none context will be propagated
..

}

One proposal is to offer a EE version of CompletableFuture and add to Concurrency spec, so that anyone uses MP concurrency to get a useful CompletionStage. I think Nathan has some detailed design to extend ManagedExecutorService and would like to propose to the future Concurrency spec anyway, which might be ideal to bring to MP concurrency first. I don't want to steal his thunder. Nathan, please explain in more details.

Thanks
Emily

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit


To post to this group, send email to

Reza Rahman

unread,
Aug 1, 2018, 10:57:40 PM8/1/18
to Eclipse MicroProfile
When Jakarta EE becomes a reality, what would be really nice is being able to define named executor services via an annotation and being able to inject those - similar to what was done for data sources, JMS resources, etc. For now, I think defining that with @Inject is fine.

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

Nathan Rauh

unread,
Aug 6, 2018, 11:18:37 AM8/6/18
to microp...@googlegroups.com
Agreed, annotative config in Jakarta EE is the long term goal.
For now, I have added a pull to the sandbox location including the proposed interfaces/JavaDoc for @ManagedExecutorConfig and @ThreadContextConfig
https://github.com/eclipse/microprofile-sandbox/pull/15
with the ability to configure which context types and otherwise just the other two attributes from the earlier discussion.
The pull also includes interfaces/JavaDoc for the ThreadContextProvider SPI from earlier discussions.

.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/462bb2b1-e8c5-4f05-91b7-27b2c9b27f5c%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/52cc6aac-7efd-4da0-a30f-bbc88d8fa226%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit

https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/671f7198-928a-4cef-a973-4c6acd214441%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Emily Jiang

unread,
Aug 12, 2018, 11:14:59 AM8/12/18
to Eclipse MicroProfile
Great discussions. I like the proposal. As for the details of propagating cdi beans, I think we can introduce another method to make the beans to be registered per se, so that they can be propagated. I think targeting scopes e.g. request/session may not be ideal. Anyway, that is a detailed design.

For now, I would like to ask for votes to say whether we would like to see this proposal going forward and have mp-concurrency repo created. If you have a better name for the repo, please suggest.

I have my +1 here.

Thanks
Emily

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

m.reza.rahman

unread,
Aug 12, 2018, 11:37:54 AM8/12/18
to microp...@googlegroups.com
Definite +1.

Sent via the Samsung Galaxy S7, an AT&T 4G LTE smartphone

Guillermo González de Agüero

unread,
Aug 12, 2018, 11:45:14 AM8/12/18
to microp...@googlegroups.com
+1.

.


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.


To unsubscribe from this group and all its topics, send an email to


To post to this group, send email to


To view this discussion on the web visit

You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.

To post to this group, send email to microp...@googlegroups.com.

Martijn Verburg

unread,
Aug 12, 2018, 1:00:49 PM8/12/18
to MicroProfile

Stephane Epardaud

unread,
Aug 13, 2018, 11:56:51 AM8/13/18
to microp...@googlegroups.com
Hi,

The proposed API and SPI look nice, but based on the existing implementation of Reactive Contexts, which is already used by RESTEasy, and which has seen real-world use and grew features out of real-world use-cases, I have filed the following issues:


I suspect that mp-concurrency will likely replace Reactive Contexts, if only because I suspect RESTEasy will not be able to depend on two separate context libraries, and I also don't think the world needs more than one solution for that problem. For that reason, we need to make sure that mp-concurrency supports _at least_ the existing features of Reactive Contexts that RESTEasy requires, for which I've filed those issues.

Cheers.


For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Emily Jiang

unread,
Aug 13, 2018, 5:53:24 PM8/13/18
to Eclipse MicroProfile
Thank you Stephane for bringing this up! Agreed! We should coordinate the effort and make developers life easier not harder. Once the mp-concurrency repo is created, the following issues should be migrated over. You should be part of the mp-concurrency workgroup as well.

If I don't hear any objection today, I will file a bugzilla tomorrow to get the mp-concurrency repo created.

Emily
+1
Cheers,
Martijn


+1.

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/e8a62fbe-5c18-479a-8550-07c18b715ce1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/CAG1ZpUaHViC2Hp%3DAD0YLgtkoL6%2BKXnSpHJ%2BAOAgbUFLguNP4Xg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.
To post to this group, send email to microp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microprofile/CAP7YuAQmxJwaYD5dpWc9o4-bTMMZ-0SDr9k0jvtwq9OU0b8Wdw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


--
Stéphane Épardaud

Emily Jiang

unread,
Aug 14, 2018, 5:14:59 PM8/14/18
to Eclipse MicroProfile
I have created this bugzilla to get our repo microprofile-concurrency created.

John C or Kevin S, please put your +1 in this ticket, so that the creation can happen.

Thanks
Emily
+1
Cheers,
Martijn


+1.

.
To post to this group, send email to
microprofile@googlegroup

Emily Jiang

unread,
Aug 16, 2018, 7:28:15 AM8/16/18
to Eclipse MicroProfile
The repo microprofile-concurrency  has been created (Thank you Kevin for your +1!)! I have created a gitter room for it. Please join in.

Arthur, please start creating PRs to bring the APIs and readme over. Stephane, please migrate the issues over as well. Arthur, can you create a doodle pool to gather time and interests for the upcoming weekly hangout?

Thanks
Emily
</block

Nathan Rauh

unread,
Aug 22, 2018, 5:52:34 PM8/22/18
to microp...@googlegroups.com
Thanks for creating the repo and gitter room.
It looks like Arthur hasn't gotten around to opening the pull to bring the sandbox API and readme over yet, so I went ahead and opened one,
https://github.com/eclipse/microprofile-concurrency/pull/4

The API and readme under this pull are identical to what is in the sandbox except for:
- license added to the readme (this was required by the validation checking)
- unused imports removed (also required by the validation checking)
- gitter link added to the readme to match the other microprofile projects



From:        "'Emily Jiang' via Eclipse MicroProfile" <microp...@googlegroups.com>
To:        Eclipse MicroProfile <microp...@googlegroups.com>
Date:        08/16/2018 06:28 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile




The repo microprofile-concurrency has been created (Thank you Kevin for your +1!)! I have created a gitter room for it. Please join in.

Arthur, please start creating PRs to bring the APIs and readme over. Stephane, please migrate the issues over as well. Arthur, can you create a doodle pool to gather time and interests for the upcoming weekly hangout?

Thanks
Emily


On Tuesday, August 14, 2018 at 10:14:59 PM UTC+1, Emily Jiang wrote:

I have created this bugzillato get our repo microprofile-concurrency created.

.
To post to this group, send email to
microprofile@googlegroup

</block

--
You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
microprofile...@googlegroups.com.
To post to this group, send email to
microp...@googlegroups.com

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/f3525c34-0266-4b55-919d-f368bcf3ff88%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Emily Jiang

unread,
Aug 23, 2018, 5:18:16 AM8/23/18
to Eclipse MicroProfile
My apologies, Nathan! I meant you not Arthur:o. Please create a doodle to form a workgroup in order to discuss the PR and the upcoming issues.

Thanks
Emily

.
To unsubscribe from this group and all its topics, send an email to
microprofile+unsubscribe@googlegroups.com.


To post to this group, send email to


To view this discussion on the web visit

Nathan Rauh

unread,
Aug 23, 2018, 10:18:09 AM8/23/18
to microp...@googlegroups.com
The poll for MP Concurency hangout meeting times is available here.  I tried to choose a variety of times that don't conflict with any other MicroProfile meetings,
https://doodle.com/poll/aembyxkau54bq6ak
I'll keep it open for a week or so to give everyone a chance to vote.

Also, I'll need someone with commit authority to merge pull #4 (below)

</block

.


To view this discussion on the web visit

https://groups.google.com/d/msgid/microprofile/f3525c34-0266-4b55-919d-f368bcf3ff88%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.

--

You received this message because you are subscribed to a topic in the Google Groups "Eclipse MicroProfile" group.
To unsubscribe from this topic, visit

https://groups.google.com/d/topic/microprofile/jKFu-IS_U90/unsubscribe.


To unsubscribe from this group and all its topics, send an email to

microprofile...@googlegroups.com.


To post to this group, send email to

microp...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/64efd991-23d0-4f8d-adae-ca4e8dccc3e0%40googlegroups.com.
For more options, visit
https://groups.google.com/d/optout.


Stephane Epardaud

unread,
Aug 24, 2018, 3:35:03 AM8/24/18
to microp...@googlegroups.com
Some of the times are marked PM, but others have no such marking, and I'm not sure what the assumption should be since it's likely not 24H format. Can you clarify please?

</block


--

You received this message because you are subscribed to the Google Groups "Eclipse MicroProfile" group.

To unsubscribe from this group and stop receiving emails from it, send an email to microprofile...@googlegroups.com.


To post to this group, send email to microp...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Ondro Mihályi

unread,
Aug 24, 2018, 4:06:26 AM8/24/18
to MicroProfile
Stephane is right, the doodle poll is weird. It doesn't show the time in users' timezone and some times are without am/pm. Nathan, could you update the poll (or recreate it) so that it shows times in user's timezone (Prague in my case), like this:

image.png

--Ondro

pi 24. 8. 2018 o 9:35 Stephane Epardaud <stephane...@gmail.com> napísal(a):

Nathan Rauh

unread,
Aug 24, 2018, 9:30:06 AM8/24/18
to microp...@googlegroups.com
Here is another copy of the poll that includes the local time zone rather than GMT.
https://doodle.com/poll/cuei2m64c8z4uybe

The downside of this one is that in order to do this, I had to select specific dates even though the meeting is meant to repeat.  I found this confusing, which is why I initially created the poll the other way.

Now that there are two polls, I'll plan to combine the output so that we don't lose any votes that have already been cast.  If a person votes in both polls, I'll assume that their response in the second poll takes precedence.

</block



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CACZTZYWy%3DVNpJsLk4uNkYhLbpj12et-pVsGypXo2PESkLKLOug%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Stephane Epardaud

unread,
Aug 24, 2018, 10:36:24 AM8/24/18
to microp...@googlegroups.com
Thanks.

</block



--
Stéphane Épardaud


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Nathan Rauh

unread,
Aug 30, 2018, 3:52:56 PM8/30/18
to microp...@googlegroups.com
Tallying up the votes from the poll, the most popular (all green except for one yellow check mark) is Fridays at 3:30 PM GMT, which if I'm converting properly is
5:30 PM CEST (Paris/Prague)
4:30 PM BST (London)
3:30 PM GMT
11:30 AM EDT (US Eastern)
10:30 AM CDT (US Central)
8:30 AM PDT (US West coast)

Let's go ahead and schedule the first meeting for Friday (Sept 7) at this time.

It turns out I don't have authority to add events to the calendar.  Could someone with authority add a MP Concurrency Hangout event at this time on Friday, Sept 7, using the default zoom call that other MicroProfile hangouts use?
https://calendar.google.com/calendar/embed?src=gbnbc373ga40n0tvbl88nkc3r4%40group.calendar.google.com&ctz=GMT

Also, I'm still looking for someone with authority to merge the pull that copies our sandbox proposal over to the microprofile-concurrency repo,
https://github.com/eclipse/microprofile-concurrency/pull/4

And we need to get the remaining issues that Stéphane opened moved over to the new repository,
I can look into that next week prior to the meeting if it isn't handled by anyone else before then.





From:        Stephane Epardaud <stephane...@gmail.com>
To:        microp...@googlegroups.com
Date:        08/24/2018 09:36 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile
Sent by:        microp...@googlegroups.com




Thanks.

On Fri, 24 Aug 2018 at 15:30, Nathan Rauh <natha...@us.ibm.com> wrote:
Here is another copy of the poll that includes the local time zone rather than GMT.
https://doodle.com/poll/cuei2m64c8z4uybe

The downside of this one is that in order to do this, I had to select specific dates even though the meeting is meant to repeat.  I found this confusing, which is why I initially created the poll the other way.


Now that there are two polls, I'll plan to combine the output so that we don't lose any votes that have already been cast.  If a person votes in both polls, I'll assume that their response in the second poll takes precedence.





From:        
"Ondro Mihályi" <ondrej....@gmail.com>
To:        
MicroProfile <microp...@googlegroups.com>
Date:        
08/24/2018 03:09 AM
Subject:        
Re: [microprofile] Bring Concurrency to MicroProfile
Sent by:        
microp...@googlegroups.com




Stephane is right, the doodle poll is weird. It doesn't show the time in users' timezone and some times are without am/pm. Nathan, could you update the poll (or recreate it) so that it shows times in user's timezone (Prague in my case), like this:



stephane...@gmail.com> napísal(a):
natha...@us.ibm.com> wrote:

</block



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CAKU9E9sHE7fVhFtXAsba2U3bcRR0n8F%2BfGtY24LQfGYS4iTkrw%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.[attachment "noname" deleted by Nathan Rauh/Rochester/IBM] [attachment "noname" deleted by Nathan Rauh/Rochester/IBM]


Stephane Epardaud

unread,
Aug 31, 2018, 4:57:49 AM8/31/18
to microp...@googlegroups.com
And we need to get the remaining issues that Stéphane opened moved over to the new repository, 

Moved, with comments and all? Or roughly re-created? The first kind of move can only be done by github.

</block



--
Stéphane Épardaud



--
Stéphane Épardaud


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Emily Jiang

unread,
Aug 31, 2018, 9:55:41 AM8/31/18
to Eclipse MicroProfile
I have created the calendar entry for you together with an empty minutes google doc to log minutes. All set, I think. Please check to see whether the details are accurate.
By the way, anyone should be able to create the calendar entry. I am not sure why it does not work for you, Nathan. Cesar/John, do you know why?
Thanks
Emily

Nathan Rauh

unread,
Sep 1, 2018, 4:42:08 PM9/1/18
to microp...@googlegroups.com
Stéphane,
I think roughly re-creating the issues should be fine, maybe with a link back to the original.  The most important thing is not to lose track of them so that we can get them incorporated into the spec.

Emily,
Thanks for getting the calendar entry created. I checked with some co-workers and none of them had authority to add calendar entries either.

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CAKU9E9tEM6xL9EgYvDvsPz%3DJDe%2BTMZz_kWjedkiiUpuhBx56Eg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Nathan Rauh

unread,
Sep 12, 2018, 5:46:42 PM9/12/18
to microp...@googlegroups.com
Stéphane,

In giving some more thought to the issues that you opened (linking them here for others who are following the discussion),
https://github.com/eclipse/microprofile-concurrency/issues/5
https://github.com/eclipse/microprofile-concurrency/issues/6
https://github.com/eclipse/microprofile-concurrency/issues/7

I'm starting to realize that I may have gotten us started in the wrong direction with the builder API that I was exploring last week.  Getting thread context propagation automatically plugged in to RxJava isn't really an API level task, it's SPI level, and this may be why some of the requirements aren't quite matching up.  Looking over the RxJava plugin example that you linked, it seems to me this could be more easily achieved making direct use of the SPI, which I believe is more appropriate here anyway, given that we are integrating technologies together rather than writing application code.

I spent some time coding up what this plugin might look like using the SPI (note that I haven't actually tried it or even compiled against the real interfaces).
Here is how I would translate your example https://reactiverse.io/reactive-contexts/over to using the SPI,

    finalstaticclassContextCapturerSingle<T> implementsSingle.OnSubscribe<T> {
        privatefinalSingle.OnSubscribe<T> source;
        privatefinalList<ThreadContextSnapshot> contextSnapshots = newArrayList<ThreadContextSnapshot>();

        publicContextCapturerSingle(Single.OnSubscribe<T> source) {
            this.source = source;

            // oversimplified to get the point across (the following needs to handle prereq context
            // and reject duplicates, and could be optimized to be done only once per class loader)
            for(ThreadContextProvider provider : ServiceLoader.load(ThreadContextProvider.class)) {
                contextSnapshots.add(provider.currentContext(Collections.EMPTY_MAP));
            }
        }

        @Override
        publicvoidcall(SingleSubscriber<? superT> t) {
            LinkedList<ThreadContextController> appliedContexts = newLinkedList<ThreadContextController>();
            try{
                for(ThreadContextSnapshot contextSnapshot : contextSnapshots) {
                    appliedContexts.addFirst(contextSnapshot.begin());
                }

                source.call(newOnAssemblySingleSubscriber<T>(t, contextSnapshots));
            }
            finally{
                for(ThreadContextController controller : appliedContexts) {
                    controller.endContext();
                }
            }
        }

        staticfinalclassOnAssemblySingleSubscriber<T> extendsSingleSubscriber<T> {
            privatefinalSingleSubscriber<? superT> actual;
            privatefinalList<ThreadContextSnapshot> contextSnapshots;

            OnAssemblySingleSubscriber(SingleSubscriber<? superT> actual, List<ThreadContextSnapshot> contextSnapshots) {
                this.actual = actual;
                this.contextSnapshots = contextSnapshots;
                actual.add(this);
            }

            @Override
            publicvoidonError(Throwable e) {
                LinkedList<ThreadContextController> appliedContexts = newLinkedList<ThreadContextController>();
                try{
                    for(ThreadContextSnapshot contextSnapshot : contextSnapshots) {
                        appliedContexts.addFirst(contextSnapshot.begin());
                    }

                    actual.onError(e);
                }
                finally{
                    for(ThreadContextController controller : appliedContexts) {
                        controller.endContext();
                    }
                }
            }

            @Override
            publicvoidonSuccess(T t) {
                LinkedList<ThreadContextController> appliedContexts = newLinkedList<ThreadContextController>();
                try{
                    for(ThreadContextSnapshot contextSnapshot : contextSnapshots) {
                        appliedContexts.addFirst(contextSnapshot.begin());
                    }

                    actual.onSuccess(t);
                }
                finally{
                    for(ThreadContextController controller : appliedContexts) {
                        controller.endContext();
                    }
                }
            }
        }
    }

I would like to suggest that using the SPI ought to be the starting point for solving these issues, and that where the SPI isn't sufficient, we should aim to improve it.  One concern that I can see might be the section that I left out with the 'oversimplified' comment.  If this is a concern, there may be some things we can do in the SPI to address it, such as building in a static method to do all of this (load providers, validation against duplicates, return ordered lists of providers based on declared prerequisite context types, and potentially even caching per unique class loader).

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/OFE699C776.17CD1234-ON002582FB.00712F9D-862582FB.0071B4D5%40notes.na.collabserv.com.
For more options, visit
https://groups.google.com/d/optout.


Stephane Epardaud

unread,
Sep 13, 2018, 4:08:45 AM9/13/18
to microp...@googlegroups.com
Hi,


Where I factored in the provider iteration into our API classes, because the SPI is too poor and error-prone and not DRY to be accessed by clients, as I'm sure you must have realised with all the boilerplate you had to copy/paste ;)

If we can move those abstractions in the spec that'd be great.

The other thing that SmallRyeConcurrencyProvider.captureContext() does is that it captures the thread context states, but also the manager who captured them (which is the one with the list of providers), so when I begin/endContext on those states, I also make sure that manager is installed/deinstalled in a thread-local to make sure that two different applications won't trip over a manager which is not theirs. That's what I did for ReactiveContexts to solve the issue for multiple applications having different sets of providers/propagators.

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Nathan Rauh

unread,
Sep 13, 2018, 12:45:12 PM9/13/18
to microp...@googlegroups.com
Stéphane,

Thanks for providing the the example SPI usage in that github repo.  I coded up a potential static utility method for ThreadContextProvider SPI that ought to eliminate all of the boilerplate code.  It creates multiple-context versions ThreadContextSnapshot/ThreadContextController, so it has identical usage to the rest of the SPI once you obtain it.  It's under,
https://github.com/eclipse/microprofile-concurrency/pull/13

With this, usage based on your rxjava example would be something like:


    finalstaticclassContextCapturerSingle<T> implementsSingle.OnSubscribe<T> {
        privatefinalSingle.OnSubscribe<T> source;
        privatefinalThreadContextSnapshot contextSnapshot;


        publicContextCapturerSingle(Single.OnSubscribe<T> source) {
            this.source = source;
            contextSnapshot = ThreadContextProvider.captureAllContext(Collections.EMPTY_MAP);

        }

        @Override
        publicvoidcall(SingleSubscriber<? superT> t) {
            ThreadContextController controller = contextSnapshot.begin();
            try{
                source.call(newOnAssemblySingleSubscriber<T>(t, contextSnapshot));
            } finally{

                controller.endContext();
            }
        }

        staticfinalclassOnAssemblySingleSubscriber<T> extendsSingleSubscriber<T> {
            privatefinalSingleSubscriber<? superT> actual;
            privatefinalThreadContextSnapshot contextSnapshot;

            OnAssemblySingleSubscriber(SingleSubscriber<? superT> actual, ThreadContextSnapshot contextSnapshot) {
                this.actual = actual;
                this.contextSnapshot = contextSnapshot;
                actual.add(this);
            }

            @Override
            publicvoidonError(Throwable e) {
                ThreadContextController controller = contextSnapshot.begin();
                try{
                    actual.onError(e);
                } finally{
                    controller.endContext();
                }
            }

            @Override
            publicvoidonSuccess(T t) {
                ThreadContextController controller = contextSnapshot.begin();
                try{
                    actual.onSuccess(t);
                } finally{
                    controller.endContext();
                }
            }
        }
    }

Would this meet your needs?

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CAKU9E9s7%2BzAxmp-NMjwyrVi0Yq%3D2PcH__VRvGT6CCF_n4mk_ZA%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Stephane Epardaud

unread,
Sep 14, 2018, 3:16:24 AM9/14/18
to microp...@googlegroups.com
Thanks. I'll reply to the PR.

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Nathan Rauh

unread,
Sep 14, 2018, 11:08:23 AM9/14/18
to microp...@googlegroups.com
Stéphane,

In the pull you indicated you are really wanting to use ThreadContext for this (and I can see how it is undesirable to have implementation of the static method within the spec interfaces).
The main obstacle with the ThreadContext API is that it doesn't allow you to isolate thread context begin from end/restore.  We don't have this in the API intentionally, because the application shouldn't be put in a position where it can corrupt thread context for future usage by forgetting to restore it.

However, what if we instead added a method to ThreadContext like this,

    /**
     * <p>Creates an <code>Executor</code>that runs tasks on the same thread from which
     * <code>execute</code>is invoked but with context that is captured from the thread
     * that invokes <code>withCurrentContext</code>.</p>
     *
     * @returnan executor that wraps the <code>execute</code>method with context.
     */
    Executor withCurrentContext();

which you would be able to use as follows,

    finalstaticclassContextCapturerSingle<T>implements Single.OnSubscribe<T> {
        private final Single.OnSubscribe<T> source;
        privatefinalExecutor contextSnapshot;


        publicContextCapturerSingle(Single.OnSubscribe<T> source) {
            this.source = source;
            contextSnapshot = threadContext.withCurrentContext();

        }

        @Override
        publicvoidcall(SingleSubscriber<? superT> t) {
            contextSnapshot.execute(() -> source.call(newOnAssemblySingleSubscriber<T>(t, contextSnapshot)));

        }

        staticfinalclassOnAssemblySingleSubscriber<T> extendsSingleSubscriber<T> {
            privatefinalSingleSubscriber<? superT> actual;
            privatefinalExecutor contextSnapshot;

            OnAssemblySingleSubscriber(SingleSubscriber<? superT> actual, Executor contextSnapshot) {

                this.actual = actual;
                this.contextSnapshot = contextSnapshot;
                actual.add(this);
            }

            @Override
            publicvoidonError(Throwable e) {
                contextSnapshot.execute(() -> actual.onError(e));
            }

            @Override
            publicvoidonSuccess(T t) {
                contextSnapshot.execute(() -> actual.onSuccess(t));

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CAKU9E9vvb8r7co-8oRHvRH7vNUwh-%2Bu4cGegkQ8dtaTci3B6uw%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Stephane Epardaud

unread,
Sep 17, 2018, 9:12:14 AM9/17/18
to microp...@googlegroups.com
That does indeed look like it would do the job.

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud


For more options, visit https://groups.google.com/d/optout.



--
Stéphane Épardaud

Nathan Rauh

unread,
Sep 17, 2018, 10:42:42 AM9/17/18
to microp...@googlegroups.com
Stéphane,

I added pull #15 to make this change below,
https://github.com/eclipse/microprofile-concurrency/pull/15

Would you mind reviewing?





From:        Stephane Epardaud <stephane...@gmail.com>
To:        microp...@googlegroups.com
Date:        09/17/2018 08:12 AM
Subject:        Re: [microprofile] Bring Concurrency to MicroProfile
Sent by:        microp...@googlegroups.com




That does indeed look like it would do the job.

On Fri, 14 Sep 2018 at 17:08, Nathan Rauh <natha...@us.ibm.com> wrote:
Stéphane,

In the pull you indicated you are really wanting to use ThreadContext for this (and I can see how it is undesirable to have implementation of the static method within the spec interfaces).
The main obstacle with the ThreadContext API is that it doesn't allow you to isolate thread context begin from end/restore.  We don't have this in the API intentionally, because the application shouldn't be put in a position where it can corrupt thread context for future usage by forgetting to restore it.


However, what if we instead added a method to ThreadContext like this,


   
/**
     *
<p>Creates an <code>Executor</code>that runs tasks on the same thread from which
     *
<code>execute</code>is invoked but with context that is captured from the thread
     * that invokes
<code>withCurrentContext</code>.</p>
     *
     *
@returnan executor that wraps the <code>execute</code>method with context.
     */

    Executor withCurrentContext();


which you would be able to use as follows,


   
finalstaticclassContextCapturerSingle<T>implementsSingle.OnSubscribe<T> {
       
private final Single.OnSubscribe<T> source;
       
privatefinalExecutor contextSnapshot;

</block



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud



--
Stéphane Épardaud

.
To view this discussion on the web visit
https://groups.google.com/d/msgid/microprofile/CAKU9E9ss90y9BOTgSsqd0rmrtxGbfeneH6B7Km9une9w0zTf%3Dg%40mail.gmail.com.
For more options, visit
https://groups.google.com/d/optout.


Reply all
Reply to author
Forward
0 new messages