diff --git a/org.springframework.integration.event/.classpath b/org.springframework.integration.event/.classpath new file mode 100644 index 0000000000..1edf4aed5a --- /dev/null +++ b/org.springframework.integration.event/.classpath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/org.springframework.integration.event/.project b/org.springframework.integration.event/.project new file mode 100644 index 0000000000..4c31b0b880 --- /dev/null +++ b/org.springframework.integration.event/.project @@ -0,0 +1,17 @@ + + + org.springframework.integration.event + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/org.springframework.integration.event/build.xml b/org.springframework.integration.event/build.xml new file mode 100644 index 0000000000..03dc5b9710 --- /dev/null +++ b/org.springframework.integration.event/build.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.springframework.integration.event/ivy.xml b/org.springframework.integration.event/ivy.xml new file mode 100644 index 0000000000..3732f1b9c8 --- /dev/null +++ b/org.springframework.integration.event/ivy.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventSource.java b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventSource.java new file mode 100644 index 0000000000..d482a527c5 --- /dev/null +++ b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventSource.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2008 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.event; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.message.MessageChannelTemplate; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * A message source for passing Spring + * {@link ApplicationEvent ApplicationEvents} within messages. + * + * @author Mark Fisher + */ +public class ApplicationEventSource implements ApplicationListener { + + private final MessageChannel channel; + + private List> eventTypes = new ArrayList>(); + + private final MessageChannelTemplate channelTemplate = new MessageChannelTemplate(); + + + public ApplicationEventSource(MessageChannel channel) { + Assert.notNull(channel, "channel must not be null"); + this.channel = channel; + } + + + /** + * 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.sendMessage(event); + return; + } + for (Class eventType : this.eventTypes) { + if (eventType.isAssignableFrom(event.getClass())) { + this.sendMessage(event); + return; + } + } + } + + private boolean sendMessage(ApplicationEvent event) { + return this.channelTemplate.send( + new GenericMessage(event), this.channel); + } + +} diff --git a/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventTarget.java b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventTarget.java new file mode 100644 index 0000000000..9c6895532a --- /dev/null +++ b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/ApplicationEventTarget.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2008 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.event; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.integration.message.Message; +import org.springframework.integration.message.MessageTarget; + +/** + * A message target 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} sent to this target. + * + * @author Mark Fisher + */ +public class ApplicationEventTarget implements MessageTarget, ApplicationEventPublisherAware { + + private ApplicationEventPublisher applicationEventPublisher; + + + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + public boolean send(Message message) { + this.applicationEventPublisher.publishEvent( + new MessagingEvent((Message) message)); + return true; + } + +} diff --git a/org.springframework.integration.event/src/main/java/org/springframework/integration/event/MessagingEvent.java b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/MessagingEvent.java new file mode 100644 index 0000000000..5293c44c74 --- /dev/null +++ b/org.springframework.integration.event/src/main/java/org/springframework/integration/event/MessagingEvent.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2008 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.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/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventSourceTests.java b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventSourceTests.java new file mode 100644 index 0000000000..55d7ce039f --- /dev/null +++ b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventSourceTests.java @@ -0,0 +1,114 @@ +/* + * Copyright 2002-2008 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.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.PollableChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.message.Message; + +/** + * @author Mark Fisher + */ +public class ApplicationEventSourceTests { + + @Test + public void testAnyApplicationEventSentByDefault() { + QueueChannel channel = new QueueChannel(); + ApplicationEventSource adapter = new ApplicationEventSource(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() { + QueueChannel channel = new QueueChannel(); + ApplicationEventSource adapter = new ApplicationEventSource(channel); + List> eventTypes = new ArrayList>(); + eventTypes.add(TestApplicationEvent1.class); + adapter.setEventTypes(eventTypes); + 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("applicationEventSourceTests.xml", this.getClass()); + PollableChannel channel = (PollableChannel) 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.stop(); + Message stoppedEventMessage = channel.receive(0); + assertNotNull(stoppedEventMessage); + assertEquals(ContextStoppedEvent.class, stoppedEventMessage.getPayload().getClass()); + context.close(); + Message closedEventMessage = channel.receive(0); + assertNotNull(closedEventMessage); + assertEquals(ContextClosedEvent.class, closedEventMessage.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/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventTargetTests.java b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventTargetTests.java new file mode 100644 index 0000000000..3481a1dcad --- /dev/null +++ b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/ApplicationEventTargetTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2008 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.event; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.integration.message.Message; +import org.springframework.integration.message.StringMessage; + +/** + * @author Mark Fisher + */ +public class ApplicationEventTargetTests { + + @Test + @SuppressWarnings("unchecked") + public void testSendingEvent() throws InterruptedException { + TestApplicationEventPublisher publisher = new TestApplicationEventPublisher(); + ApplicationEventTarget adapter = new ApplicationEventTarget(); + adapter.setApplicationEventPublisher(publisher); + assertNull(publisher.getLastEvent()); + Message message = new StringMessage("testing"); + adapter.send(message); + ApplicationEvent event = publisher.getLastEvent(); + assertEquals(MessagingEvent.class, event.getClass()); + assertEquals(message, ((MessagingEvent) event).getMessage()); + } + + + private static class TestApplicationEventPublisher implements ApplicationEventPublisher { + + private volatile ApplicationEvent lastEvent; + + public ApplicationEvent getLastEvent() { + return this.lastEvent; + } + + public void publishEvent(ApplicationEvent event) { + this.lastEvent = event; + } + } + +} diff --git a/org.springframework.integration.event/src/test/java/org/springframework/integration/event/applicationEventSourceTests.xml b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/applicationEventSourceTests.xml new file mode 100644 index 0000000000..7729a92f1b --- /dev/null +++ b/org.springframework.integration.event/src/test/java/org/springframework/integration/event/applicationEventSourceTests.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/org.springframework.integration.event/template.mf b/org.springframework.integration.event/template.mf new file mode 100644 index 0000000000..343e765dea --- /dev/null +++ b/org.springframework.integration.event/template.mf @@ -0,0 +1,12 @@ +Bundle-SymbolicName: org.springframework.integration.event +Bundle-Name: Spring Integration ApplicationEvent Support +Bundle-Vendor: SpringSource +Bundle-ManifestVersion: 2 +Import-Template: + org.springframework.integration.*;version="[1.0.0, 1.0.1)", + org.springframework.context;version="[2.5.5.A, 3.0.0)", + org.springframework.util;version="[2.5.5.A, 3.0.0)", + org.apache.commons.logging;version="[1.1.1, 2.0.0)" +Unversioned-Imports: + org.w3c.dom +