Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CDI-650 Introduce asynchronous event notification options #337

Merged
merged 1 commit into from Nov 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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