Skip to content

Commit

Permalink
CDI-650 Introduce asynchronous event notification options (#337)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkouba authored and antoinesd committed Nov 29, 2016
1 parent 336dbec commit 7a0c932
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 4 deletions.
6 changes: 4 additions & 2 deletions api/src/main/java/javax/enterprise/event/Event.java
Expand Up @@ -20,6 +20,7 @@
import java.lang.annotation.Annotation;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;

import javax.enterprise.util.TypeLiteral;

/**
Expand Down Expand Up @@ -129,7 +130,7 @@ public interface Event<T> {
* </p>
*
* @param event the event object
* @param executor a custom executor to execute asynchronous event
* @param options the notification options
* @return a {@link CompletionStage} allowing further pipeline composition on the asynchronous operation.
* Default asynchronous execution facility is container specific.
* If any observer notified by this event throws an exception
Expand All @@ -140,7 +141,7 @@ public interface Event<T> {
*
* @since 2.0
*/
public <U extends T> CompletionStage<U> fireAsync(U event, Executor executor);
public <U extends T> CompletionStage<U> fireAsync(U event, NotificationOptions options);

/**
* <p>
Expand Down Expand Up @@ -181,4 +182,5 @@ public interface Event<T> {
* is not a qualifier type
*/
public <U extends T> Event<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);

}
@@ -0,0 +1,76 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2016, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.enterprise.event;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;

/**
* The immutable implementation of {@link NotificationOptions}.
*
* @author Martin Kouba
*
*/
class ImmutableNotificationOptions implements NotificationOptions {

private final Executor executor;

private final Map<String, Object> options;

private ImmutableNotificationOptions(Executor executor, Map<String, Object> options) {
this.executor = executor;
this.options = new HashMap<>(options);
}

@Override
public Executor getExecutor() {
return executor;
}

@Override
public Object get(String name) {
return options.get(name);
}

static class Builder implements javax.enterprise.event.NotificationOptions.Builder {

private Executor executor;

private Map<String, Object> options;

Builder() {
this.options = new HashMap<>();
}

public Builder setExecutor(Executor executor) {
this.executor = executor;
return this;
}

public Builder set(String name, Object value) {
options.put(name, value);
return this;
}

public ImmutableNotificationOptions build() {
return new ImmutableNotificationOptions(executor, options);
}

}

}
86 changes: 86 additions & 0 deletions api/src/main/java/javax/enterprise/event/NotificationOptions.java
@@ -0,0 +1,86 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2016, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.enterprise.event;

import java.util.concurrent.Executor;

/**
* Notification options are used to configure observer notification.
*
* @author Martin Kouba
* @see Event#fireAsync(Object, NotificationOptions)
* @since 2.0
*/
public interface NotificationOptions {

/**
*
* @return the executor used to execute an asynchronous event
*/
Executor getExecutor();

/**
*
* @param optionName
* @return the value of an option or <code>null</code> if no option for the given name exists
*/
Object get(String optionName);

/**
*
* @param executor
* @return an immutable holder of an executor
*/
static NotificationOptions ofExecutor(Executor executor) {
return builder().setExecutor(executor).build();
}

/**
*
* @param optionName
* @param optionValue
* @return an immutable holder of a single option
*/
static NotificationOptions of(String optionName, Object optionValue) {
return builder().set(optionName, optionValue).build();
}

/**
*
* @return the options builder
*/
static Builder builder() {
return new ImmutableNotificationOptions.Builder();
}

/**
* Notification options builder.
*
* @author Martin Kouba
* @since 2.0
*/
interface Builder {

Builder setExecutor(Executor executor);

Builder set(String optionName, Object optionValue);

NotificationOptions build();

}

}
@@ -0,0 +1,44 @@
package org.jboss.cdi.api.test.event;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;

import java.time.Duration;
import java.util.concurrent.Executor;

import javax.enterprise.event.NotificationOptions;

import org.testng.annotations.Test;

/**
*
* @author Martin Kouba
*/
public class NotificationOptionsTest {

@Test
public void testBuilder() {
Duration timeout = Duration.ofDays(1);
NotificationOptions options = NotificationOptions.of("timeout", timeout);
assertEquals(timeout, options.get("timeout"));
assertNull(options.getExecutor());
assertNull(options.get("alpha"));
options = NotificationOptions.builder().set("foo", "bar").setExecutor(new Executor() {
@Override
public void execute(Runnable command) {
}
}).build();
assertEquals("bar", options.get("foo"));
assertNotNull(options.getExecutor());
options = NotificationOptions.ofExecutor(new Executor() {
@Override
public void execute(Runnable command) {
}
});
Executor executor = options.getExecutor();
assertNotNull(executor);
assertNull(options.get("timeout"));
}

}
5 changes: 3 additions & 2 deletions spec/src/main/asciidoc/core/events.asciidoc
Expand Up @@ -122,7 +122,7 @@ public interface Event<T> {
public void fire(T event);
public <U extends T> CompletionStage<U> fireAsync(U event);
public <U extends T> CompletionStage<U> fireAsync(U event, Executor executor);
public <U extends T> CompletionStage<U> fireAsync(U event, NotificationOptions options);
public Event<T> select(Annotation... qualifiers);
public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers);
Expand Down Expand Up @@ -165,7 +165,8 @@ If an instance of an annotation that is not a qualifier type is passed to `selec
The methods `fire()` and `fireAsync()` fire an event with the specified qualifiers and notify observers, as defined by <<observer_notification>>.
If the container is unable to resolve the parameterized type of the event object, it uses the specified type to infer the parameterized type of the event types.

The method `fireAsync()` may be called with a specific `Executor` object to be used to invoke observers method.
The method `fireAsync()` may be called with a `NotificationOptions` object to configure the observer methods notification, e.g. to specify an `Executor` object to be used for asynchronous delivery.
The container is permitted to define other non-portable notification options.

The following elements are container specific:

Expand Down

0 comments on commit 7a0c932

Please sign in to comment.