diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapter.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapter.java new file mode 100644 index 0000000000..78167c383a --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapter.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.integration.adapter.AbstractSourceAdapter; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * A source adapter for passing Spring + * {@link ApplicationEvent ApplicationEvents} within messages. + * + * @author Mark Fisher + */ +public class ApplicationEventSourceAdapter extends AbstractSourceAdapter implements + ApplicationListener { + + private List> eventTypes = new ArrayList>(); + + + /** + * Set the list of event types (classes that extend ApplicationEvent) that + * this adapter should send to the message channel. By default, all event + * types will be sent. + */ + public void setEventTypes(List> eventTypes) { + Assert.notEmpty(eventTypes, "at least one event type is required"); + this.eventTypes = eventTypes; + } + + public void onApplicationEvent(ApplicationEvent event) { + if (CollectionUtils.isEmpty(this.eventTypes)) { + this.sendToChannel(event); + return; + } + for (Class eventType : this.eventTypes) { + if (eventType.isAssignableFrom(event.getClass())) { + this.sendToChannel(event); + return; + } + } + } + +} diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapter.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapter.java new file mode 100644 index 0000000000..ba0c846bb8 --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.integration.adapter.AbstractTargetAdapter; + +/** + * A target adapter for publishing {@link MessagingEvent MessagingEvents}. The + * {@link MessagingEvent} is a subclass of Spring's {@link ApplicationEvent} + * used by this adapter to wrap any {@link Message} received on its channel. + * + * @author Mark Fisher + */ +public class ApplicationEventTargetAdapter extends AbstractTargetAdapter implements + ApplicationEventPublisherAware { + + private ApplicationEventPublisher applicationEventPublisher; + + + public ApplicationEventTargetAdapter() { + this.setMessageMapper(new MessagingEventMapper()); + } + + + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + @Override + protected boolean sendToTarget(MessagingEvent event) { + this.applicationEventPublisher.publishEvent(event); + return true; + } + +} diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEvent.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEvent.java new file mode 100644 index 0000000000..f83d22ca51 --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEvent.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import org.springframework.context.ApplicationEvent; +import org.springframework.integration.message.Message; + +/** + * A subclass of {@link ApplicationEvent} that wraps a {@link Message}. + * + * @author Mark Fisher + */ +public class MessagingEvent extends ApplicationEvent { + + public MessagingEvent(Message message) { + super(message); + } + + public Message getMessage() { + return (Message) this.getSource(); + } + +} diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEventMapper.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEventMapper.java new file mode 100644 index 0000000000..bb8ebf539c --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/event/MessagingEventMapper.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import org.springframework.integration.message.Message; +import org.springframework.integration.message.MessageMapper; + +/** + * A {@link MessageMapper} implementation for mapping to and from + * {@link MessagingEvent MessagingEvents}. + * + * @author Mark Fisher + */ +public class MessagingEventMapper implements MessageMapper> { + + public MessagingEvent fromMessage(Message message) { + return new MessagingEvent(message); + } + + public Message toMessage(MessagingEvent event) { + return event.getMessage(); + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapterTests.java b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapterTests.java new file mode 100644 index 0000000000..16af096948 --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventSourceAdapterTests.java @@ -0,0 +1,115 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.ContextStartedEvent; +import org.springframework.context.event.ContextStoppedEvent; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.channel.SimpleChannel; +import org.springframework.integration.message.Message; + +/** + * @author Mark Fisher + */ +public class ApplicationEventSourceAdapterTests { + + @Test + public void testAnyApplicationEventSentByDefault() { + MessageChannel channel = new SimpleChannel(); + ApplicationEventSourceAdapter adapter = new ApplicationEventSourceAdapter(); + adapter.setChannel(channel); + Message message1 = channel.receive(0); + assertNull(message1); + adapter.onApplicationEvent(new TestApplicationEvent1()); + adapter.onApplicationEvent(new TestApplicationEvent2()); + Message message2 = channel.receive(20); + assertNotNull(message2); + assertEquals("event1", ((ApplicationEvent) message2.getPayload()).getSource()); + Message message3 = channel.receive(20); + assertNotNull(message3); + assertEquals("event2", ((ApplicationEvent) message3.getPayload()).getSource()); + } + + @Test + public void testOnlyConfiguredEventTypesAreSent() { + MessageChannel channel = new SimpleChannel(); + ApplicationEventSourceAdapter adapter = new ApplicationEventSourceAdapter(); + List> eventTypes = new ArrayList>(); + eventTypes.add(TestApplicationEvent1.class); + adapter.setEventTypes(eventTypes); + adapter.setChannel(channel); + Message message1 = channel.receive(0); + assertNull(message1); + adapter.onApplicationEvent(new TestApplicationEvent1()); + adapter.onApplicationEvent(new TestApplicationEvent2()); + Message message2 = channel.receive(20); + assertNotNull(message2); + assertEquals("event1", ((ApplicationEvent) message2.getPayload()).getSource()); + Message message3 = channel.receive(0); + assertNull(message3); + } + + @Test + public void testApplicationContextEvents() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationEventSourceAdapterTests.xml", this.getClass()); + MessageChannel channel = (MessageChannel) context.getBean("channel"); + Message refreshedEventMessage = channel.receive(0); + assertNotNull(refreshedEventMessage); + assertEquals(ContextRefreshedEvent.class, refreshedEventMessage.getPayload().getClass()); + context.start(); + Message startedEventMessage = channel.receive(0); + assertNotNull(startedEventMessage); + assertEquals(ContextStartedEvent.class, startedEventMessage.getPayload().getClass()); + context.close(); + Message closedEventMessage = channel.receive(0); + assertNotNull(closedEventMessage); + assertEquals(ContextClosedEvent.class, closedEventMessage.getPayload().getClass()); + Message stoppedEventMessage = channel.receive(0); + assertNotNull(stoppedEventMessage); + assertEquals(ContextStoppedEvent.class, stoppedEventMessage.getPayload().getClass()); + } + + + private static class TestApplicationEvent1 extends ApplicationEvent { + + public TestApplicationEvent1() { + super("event1"); + } + } + + + private static class TestApplicationEvent2 extends ApplicationEvent { + + public TestApplicationEvent2() { + super("event2"); + } + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapterTests.java b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapterTests.java new file mode 100644 index 0000000000..1e4a20780c --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/ApplicationEventTargetAdapterTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.springframework.integration.adapter.event; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.integration.bus.MessageBus; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.channel.SimpleChannel; +import org.springframework.integration.message.StringMessage; +import org.springframework.integration.scheduling.Subscription; + +/** + * @author Mark Fisher + */ +public class ApplicationEventTargetAdapterTests { + + @Test + public void testSendingEvent() throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + ApplicationEventPublisher publisher = new ApplicationEventPublisher() { + public void publishEvent(ApplicationEvent event) { + latch.countDown(); + } + }; + MessageChannel channel = new SimpleChannel(); + ApplicationEventTargetAdapter adapter = new ApplicationEventTargetAdapter(); + adapter.setApplicationEventPublisher(publisher); + MessageBus bus = new MessageBus(); + bus.registerChannel("channel", channel); + bus.registerHandler("adapter", adapter, new Subscription(channel)); + bus.start(); + assertEquals(1, latch.getCount()); + channel.send(new StringMessage("123", "testing")); + latch.await(100, TimeUnit.MILLISECONDS); + assertEquals(0, latch.getCount()); + bus.stop(); + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/applicationEventSourceAdapterTests.xml b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/applicationEventSourceAdapterTests.xml new file mode 100644 index 0000000000..429ff0da6d --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/event/applicationEventSourceAdapterTests.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + +