mirror of https://github.com/apache/jclouds.git
Merge pull request #553 from nacx/eventbus-module
Added EventBus module to configure the sync and async EventBus
This commit is contained in:
commit
9cd9e4feeb
|
@ -45,8 +45,6 @@ import org.jclouds.lifecycle.Closer;
|
|||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -323,12 +321,6 @@ public class ExecutorServiceModule extends AbstractModule {
|
|||
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
EventBus provideEventBus(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads){
|
||||
return new AsyncEventBus(userThreads);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(Constants.PROPERTY_USER_THREADS)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.events.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Designates the module configures an {@link EventBus}.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ConfiguresEventBus {
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.events.config;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.events.config.annotations.AsyncBus;
|
||||
import org.jclouds.events.handlers.DeadEventLoggingHandler;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the {@link EventBus} to be used in the platform.
|
||||
* <p>
|
||||
* This class will provide an {@link AsyncEventBus} to be used to provide a basic pub/sub system for
|
||||
* asynchronous operations.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*
|
||||
* @see ExecutorServiceModule
|
||||
* @see AsyncEventBus
|
||||
* @see EventBus
|
||||
* @see AsyncBus
|
||||
*/
|
||||
@ConfiguresEventBus
|
||||
public class EventBusModule extends AbstractModule {
|
||||
/**
|
||||
* Provides an {@link AsyncEventBus} that will use the configured executor service to dispatch
|
||||
* events to subscribers.
|
||||
*/
|
||||
@Provides
|
||||
@Singleton
|
||||
AsyncEventBus provideAsyncEventBus(
|
||||
@Named(Constants.PROPERTY_USER_THREADS) final ExecutorService executor,
|
||||
final DeadEventLoggingHandler deadEventsHandler) {
|
||||
AsyncEventBus asyncBus = new AsyncEventBus("jclouds-async-event-bus", executor);
|
||||
asyncBus.register(deadEventsHandler);
|
||||
return asyncBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides asynchronous {@link EventBus}.
|
||||
*/
|
||||
@Provides
|
||||
@Singleton
|
||||
EventBus provideSyncEventBus(final DeadEventLoggingHandler deadEventsHandler) {
|
||||
EventBus syncBus = new EventBus("jclouds-sync-event-bus");
|
||||
syncBus.register(deadEventsHandler);
|
||||
return syncBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link EventBus} to be singleton and enables the {@link AsyncBus} annotation.
|
||||
*/
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(EventBus.class).annotatedWith(AsyncBus.class).to(AsyncEventBus.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.events.config.annotations;
|
||||
|
||||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
import org.jclouds.events.config.EventBusModule;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Used to configure {@link EventBus} injection, providing a flexible way to inject the
|
||||
* {@link AsyncEventBus}.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*
|
||||
* @see EventBusModule
|
||||
*/
|
||||
@Target({ANNOTATION_TYPE, FIELD, PARAMETER})
|
||||
@Retention(RUNTIME)
|
||||
@Qualifier
|
||||
public @interface AsyncBus {
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.events.handlers;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.eventbus.DeadEvent;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* Default handler for dead events.
|
||||
* <p>
|
||||
* It simply logs all dead events to allow debugging and troubleshooting.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Singleton
|
||||
public class DeadEventLoggingHandler
|
||||
{
|
||||
@Resource
|
||||
private Logger logger = Logger.NULL;
|
||||
|
||||
/**
|
||||
* Due to <a href="http://code.google.com/p/guava-libraries/issues/detail?id=783">Guava Issue
|
||||
* 786</a> {@link #handleDeadEvent(DeadEvent)} is marked <code>final</code>to avoid having
|
||||
* duplicate events.
|
||||
*/
|
||||
@Subscribe
|
||||
public final void handleDeadEvent(DeadEvent deadEvent) {
|
||||
logger.warn("detected dead event %s", deadEvent.getEvent());
|
||||
}
|
||||
}
|
|
@ -35,6 +35,8 @@ import org.jclouds.concurrent.MoreExecutors;
|
|||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.events.config.ConfiguresEventBus;
|
||||
import org.jclouds.events.config.EventBusModule;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
|
@ -109,6 +111,7 @@ public class RestContextBuilder<S, A> {
|
|||
addHttpModuleIfNeededAndNotPresent(modules);
|
||||
ifHttpConfigureRestOtherwiseGuiceClientFactory(modules);
|
||||
addExecutorServiceIfNotPresent(modules);
|
||||
addEventBusIfNotPresent(modules);
|
||||
addCredentialStoreIfNotPresent(modules);
|
||||
modules.add(new LifeCycleModule());
|
||||
modules.add(new BindPropertiesToAnnotations());
|
||||
|
@ -211,6 +214,19 @@ public class RestContextBuilder<S, A> {
|
|||
protected void addClientModule(List<Module> modules) {
|
||||
modules.add(new RestClientModule<S, A>(syncClientType, asyncClientType));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void addEventBusIfNotPresent(List<Module> modules) {
|
||||
if (!any(modules, new Predicate<Module>() {
|
||||
public boolean apply(Module input) {
|
||||
return input.getClass().isAnnotationPresent(ConfiguresEventBus.class);
|
||||
}
|
||||
}
|
||||
|
||||
)) {
|
||||
modules.add(new EventBusModule());
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void addExecutorServiceIfNotPresent(List<Module> modules) {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.events.config;
|
||||
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.events.config.annotations.AsyncBus;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link EventBusModule} class.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class EventBusModuleTest
|
||||
{
|
||||
private Injector injector;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() {
|
||||
ExecutorServiceModule executorServiceModule = new ExecutorServiceModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
|
||||
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
|
||||
super.configure();
|
||||
}
|
||||
};
|
||||
EventBusModule eventBusModule = new EventBusModule();
|
||||
injector = Guice.createInjector(executorServiceModule, eventBusModule);
|
||||
}
|
||||
|
||||
public void testAsyncExecutorIsProvided() {
|
||||
assertNotNull(injector.getInstance(AsyncEventBus.class));
|
||||
}
|
||||
|
||||
public void testAsyncAnnotatedEventBusIsBound() {
|
||||
Key<EventBus> eventBusKey = Key.get(EventBus.class, AsyncBus.class);
|
||||
EventBus eventBus = injector.getInstance(eventBusKey);
|
||||
|
||||
assertNotNull(eventBus);
|
||||
assertTrue(eventBus instanceof AsyncEventBus);
|
||||
}
|
||||
|
||||
public void testEventBusIsSingleton() {
|
||||
EventBus eventBus1 = injector.getInstance(EventBus.class);
|
||||
EventBus eventBus2 = injector.getInstance(EventBus.class);
|
||||
|
||||
assertTrue(eventBus1 == eventBus2);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.events.config.EventBusModule;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
|
@ -77,6 +78,17 @@ public class RestContextBuilderTest {
|
|||
assertEquals(modules.size(), 1);
|
||||
assertEquals(modules.remove(0), module);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddEventBusModuleIfNotPresent() {
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
EventBusModule module = new EventBusModule();
|
||||
modules.add(module);
|
||||
new RestContextBuilder<String, String>(String.class, String.class, new Properties())
|
||||
.addEventBusIfNotPresent(modules);
|
||||
assertEquals(modules.size(), 1);
|
||||
assertEquals(modules.remove(0), module);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddExecutorServiceModuleIfNotPresent() {
|
||||
|
|
Loading…
Reference in New Issue