You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/02/05 09:29:37 UTC
[3/9] cayenne git commit: CAY-2403
CAY-2403
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/ab1fd0bf
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/ab1fd0bf
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/ab1fd0bf
Branch: refs/heads/master
Commit: ab1fd0bf471954b94aba1aeda0c149175de50929
Parents: 023547e
Author: Arseni Bulatski <an...@gmail.com>
Authored: Fri Feb 2 15:24:03 2018 +0300
Committer: Arseni Bulatski <an...@gmail.com>
Committed: Fri Feb 2 15:24:03 2018 +0300
----------------------------------------------------------------------
RELEASE-NOTES.txt | 1 +
cayenne-jgroups/pom.xml | 82 +++++
.../org/apache/cayenne/event/JGroupsModule.java | 63 ++++
.../event/JGroupsServerModuleProvider.java | 50 +++
.../apache/cayenne/event/JavaGroupsBridge.java | 231 ++++++++++++++
.../cayenne/event/JavaGroupsBridgeFactory.java | 49 +++
.../cayenne/event/JavaGroupsBridgeProvider.java | 50 +++
...iguration.server.CayenneServerModuleProvider | 20 ++
.../event/CayenneJGroupsModuleProviderTest.java | 36 +++
.../event/JavaGroupsBridgeFactoryTest.java | 84 +++++
.../event/JavaGroupsBridgeProviderTest.java | 97 ++++++
cayenne-jms/pom.xml | 81 +++++
.../org/apache/cayenne/event/JMSBridge.java | 280 +++++++++++++++++
.../apache/cayenne/event/JMSBridgeFactory.java | 39 +++
.../apache/cayenne/event/JMSBridgeProvider.java | 50 +++
.../org/apache/cayenne/event/JMSModule.java | 54 ++++
.../cayenne/event/JMSServerModuleProvider.java | 50 +++
...iguration.server.CayenneServerModuleProvider | 20 ++
.../event/CayenneJMSModuleProviderTest.java | 36 +++
.../cayenne/event/JMSBridgeFactoryTest.java | 77 +++++
.../cayenne/event/JMSBridgeProviderTest.java | 87 ++++++
cayenne-xmpp/pom.xml | 86 ++++++
.../org/apache/cayenne/event/XMPPBridge.java | 308 +++++++++++++++++++
.../apache/cayenne/event/XMPPBridgeFactory.java | 41 +++
.../cayenne/event/XMPPBridgeProvider.java | 50 +++
.../org/apache/cayenne/event/XMPPModule.java | 71 +++++
.../cayenne/event/XMPPServerModuleProvider.java | 50 +++
...iguration.server.CayenneServerModuleProvider | 20 ++
.../event/CayenneXMPPModuleProviderTest.java | 36 +++
.../cayenne/event/XMPPBridgeFactoryTest.java | 72 +++++
.../cayenne/event/XMPPBridgeProviderTest.java | 105 +++++++
.../apache/cayenne/event/XMPPBridgeTest.java | 54 ++++
eventbridges/cayenne-jgroups/pom.xml | 41 ---
.../org/apache/cayenne/event/JGroupsModule.java | 63 ----
.../event/JGroupsServerModuleProvider.java | 50 ---
.../apache/cayenne/event/JavaGroupsBridge.java | 231 --------------
.../cayenne/event/JavaGroupsBridgeFactory.java | 49 ---
.../cayenne/event/JavaGroupsBridgeProvider.java | 50 ---
...iguration.server.CayenneServerModuleProvider | 20 --
.../event/CayenneJGroupsModuleProviderTest.java | 36 ---
.../event/JavaGroupsBridgeFactoryTest.java | 84 -----
.../event/JavaGroupsBridgeProviderTest.java | 97 ------
eventbridges/cayenne-jms/pom.xml | 41 ---
.../org/apache/cayenne/event/JMSBridge.java | 280 -----------------
.../apache/cayenne/event/JMSBridgeFactory.java | 39 ---
.../apache/cayenne/event/JMSBridgeProvider.java | 50 ---
.../org/apache/cayenne/event/JMSModule.java | 54 ----
.../cayenne/event/JMSServerModuleProvider.java | 50 ---
...iguration.server.CayenneServerModuleProvider | 20 --
.../event/CayenneJMSModuleProviderTest.java | 36 ---
.../cayenne/event/JMSBridgeFactoryTest.java | 77 -----
.../cayenne/event/JMSBridgeProviderTest.java | 87 ------
eventbridges/cayenne-xmpp/pom.xml | 46 ---
.../org/apache/cayenne/event/XMPPBridge.java | 308 -------------------
.../apache/cayenne/event/XMPPBridgeFactory.java | 41 ---
.../cayenne/event/XMPPBridgeProvider.java | 50 ---
.../org/apache/cayenne/event/XMPPModule.java | 71 -----
.../cayenne/event/XMPPServerModuleProvider.java | 50 ---
...iguration.server.CayenneServerModuleProvider | 20 --
.../event/CayenneXMPPModuleProviderTest.java | 36 ---
.../cayenne/event/XMPPBridgeFactoryTest.java | 72 -----
.../cayenne/event/XMPPBridgeProviderTest.java | 105 -------
.../apache/cayenne/event/XMPPBridgeTest.java | 54 ----
eventbridges/pom.xml | 82 -----
pom.xml | 4 +-
65 files changed, 2433 insertions(+), 2391 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 746012c..dbf604a 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -21,6 +21,7 @@ CAY-2393 Add sqlserver-docker profile to automate tests on SQLServer
CAY-2394 Upgrade to Apache Velocity 2.0
CAY-2395 cdbimport: add option to create project file
CAY-2396 Upgrade maven-assembly-plugin to 3.1.0
+CAY-2403 Extract eventbridges to top level
Bug Fixes:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/pom.xml b/cayenne-jgroups/pom.xml
new file mode 100644
index 0000000..9698a38
--- /dev/null
+++ b/cayenne-jgroups/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>cayenne-parent</artifactId>
+ <groupId>org.apache.cayenne</groupId>
+ <version>4.1.M2-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cayenne-jgroups</artifactId>
+ <name>cayenne-jgroups: Cayenne JGroups Event bridge</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>jgroups</groupId>
+ <artifactId>jgroups-all</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- This ensures LICENSE and NOTICE inclusion in all jars -->
+ <plugin>
+ <artifactId>maven-remote-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsModule.java b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsModule.java
new file mode 100644
index 0000000..77738c3
--- /dev/null
+++ b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsModule.java
@@ -0,0 +1,63 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.MapBuilder;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 4.0
+ */
+public class JGroupsModule implements Module {
+
+ /**
+ * A DI container key for the Map<String, String> storing
+ * {@link org.apache.cayenne.event.JavaGroupsBridge} properties
+ *
+ * @since 4.0
+ */
+ public static final String JAVA_GROUPS_BRIDGE_PROPERTIES_MAP = "cayenne.server.java_group_bridge";
+
+ public static void contributeMulticastAddress(Binder binder, String address) {
+ contributeProperties(binder).put(JavaGroupsBridge.MCAST_ADDRESS_PROPERTY, address);
+ }
+
+ public static void contributeMulticastPort(Binder binder, int port) {
+ contributeProperties(binder).put(JavaGroupsBridge.MCAST_PORT_PROPERTY, Integer.toString(port));
+ }
+
+ public static void contributeConfigUrl(Binder binder, String config) {
+ contributeProperties(binder).put(JavaGroupsBridge.JGROUPS_CONFIG_URL_PROPERTY, config);
+ }
+
+ private static MapBuilder<String> contributeProperties(Binder binder) {
+ return binder.bindMap(String.class, JAVA_GROUPS_BRIDGE_PROPERTIES_MAP);
+ }
+
+ @Override
+ public void configure(Binder binder) {
+ // init properties' defaults
+ contributeMulticastAddress(binder, JavaGroupsBridge.MCAST_ADDRESS_DEFAULT);
+ contributeMulticastPort(binder, JavaGroupsBridge.MCAST_PORT_DEFAULT_INT);
+
+ binder.bind(EventBridge.class).toProvider(JavaGroupsBridgeProvider.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsServerModuleProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsServerModuleProvider.java b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsServerModuleProvider.java
new file mode 100644
index 0000000..60c5bcd
--- /dev/null
+++ b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JGroupsServerModuleProvider.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 4.0
+ */
+public class JGroupsServerModuleProvider implements CayenneServerModuleProvider {
+
+ @Override
+ public Module module() {
+ return new JGroupsModule();
+ }
+
+ @Override
+ public Class<? extends Module> moduleType() {
+ return JGroupsModule.class;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Collection<Class<? extends Module>> overrides() {
+ Collection modules = Collections.singletonList(ServerModule.class);
+ return modules;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridge.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridge.java b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridge.java
new file mode 100644
index 0000000..cd7bae2
--- /dev/null
+++ b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridge.java
@@ -0,0 +1,231 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.jgroups.Channel;
+import org.jgroups.JChannel;
+import org.jgroups.Message;
+import org.jgroups.MessageListener;
+import org.jgroups.blocks.PullPushAdapter;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Implementation of EventBridge that passes and receives events via JavaGroups
+ * communication software.
+ *
+ * @since 1.1
+ */
+public class JavaGroupsBridge extends EventBridge implements MessageListener {
+
+ public static final String MCAST_ADDRESS_DEFAULT = "228.0.0.5";
+ public static final int MCAST_PORT_DEFAULT_INT = 22222;
+ public static final String MCAST_PORT_DEFAULT = Integer.toString(MCAST_PORT_DEFAULT_INT);
+
+ public static final String MCAST_ADDRESS_PROPERTY = "cayenne.JavaGroupsBridge.mcast.address";
+ public static final String MCAST_PORT_PROPERTY = "cayenne.JavaGroupsBridge.mcast.port";
+
+ /**
+ * Defines a property for JavaGroups XML configuration file.
+ */
+ public static final String JGROUPS_CONFIG_URL_PROPERTY = "javagroupsbridge.config.url";
+
+ // TODO: Meaning of "state" in JGroups is not yet clear to me
+ protected byte[] state;
+
+ protected Channel channel;
+ protected PullPushAdapter adapter;
+ protected String multicastAddress;
+ protected String multicastPort;
+ protected String configURL;
+
+ /**
+ * Creates new instance of JavaGroupsBridge.
+ */
+ public JavaGroupsBridge(EventSubject localSubject, String externalSubject) {
+ super(localSubject, externalSubject);
+ }
+
+ /**
+ * @since 1.2
+ */
+ public JavaGroupsBridge(Collection<EventSubject> localSubjects, String externalSubject) {
+ super(localSubjects, externalSubject);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public JavaGroupsBridge(Collection<EventSubject> localSubjects, String externalSubject, Map<String, String> properties) {
+ super(localSubjects, externalSubject);
+
+ // configure properties
+ String multicastAddress = properties.get(MCAST_ADDRESS_PROPERTY);
+ String multicastPort = properties.get(MCAST_PORT_PROPERTY);
+
+ this.configURL = properties.get(JGROUPS_CONFIG_URL_PROPERTY);
+ this.multicastAddress = (multicastAddress != null) ? multicastAddress : MCAST_ADDRESS_DEFAULT;
+ this.multicastPort = (multicastPort != null) ? multicastPort : MCAST_PORT_DEFAULT;
+ }
+
+ public String getConfigURL() {
+ return configURL;
+ }
+
+ public void setConfigURL(String configURL) {
+ this.configURL = configURL;
+ }
+
+ public String getMulticastAddress() {
+ return multicastAddress;
+ }
+
+ public void setMulticastAddress(String multicastAddress) {
+ this.multicastAddress = multicastAddress;
+ }
+
+ public String getMulticastPort() {
+ return multicastPort;
+ }
+
+ public void setMulticastPort(String multicastPort) {
+ this.multicastPort = multicastPort;
+ }
+
+ public byte[] getState() {
+ return state;
+ }
+
+ public void setState(byte[] state) {
+ this.state = state;
+ }
+
+ /**
+ * Implementation of org.javagroups.MessageListener - a callback method to process
+ * incoming messages.
+ */
+ public void receive(Message message) {
+ try {
+ CayenneEvent event = messageObjectToEvent((Serializable) message.getObject());
+ if (event != null) {
+
+ onExternalEvent(event);
+ }
+ }
+ catch (Exception ex) {
+ // TODO: Andrus, 2/8/2006 logging... Log4J was removed to make this usable on
+ // the client
+ }
+ }
+
+ @Override
+ protected void startupExternal() throws Exception {
+ // TODO: need to do more research to figure out the best default transport
+ // settings
+ // to avoid fragmentation, etc.
+
+ // if config file is set, use it, otherwise use a default
+ // set of properties, trying to configure multicast address and port
+ if (configURL != null) {
+ channel = new JChannel(configURL);
+ }
+ else {
+ String configString = buildConfigString();
+ channel = new JChannel(configString);
+ }
+
+ // Important - discard messages from self
+ channel.setOpt(Channel.LOCAL, Boolean.FALSE);
+ channel.connect(externalSubject);
+
+ if (receivesExternalEvents()) {
+ adapter = new PullPushAdapter(channel, this);
+ }
+ }
+
+ /**
+ * Creates JavaGroups configuration String, using preconfigured multicast port and
+ * address.
+ */
+ protected String buildConfigString() {
+ if (multicastAddress == null) {
+ throw new IllegalStateException("'multcastAddress' is not set");
+ }
+
+ if (multicastPort == null) {
+ throw new IllegalStateException("'multcastPort' is not set");
+ }
+
+ return "UDP(mcast_addr="
+ + multicastAddress
+ + ";mcast_port="
+ + multicastPort
+ + ";ip_ttl=32):"
+ + "PING(timeout=3000;num_initial_members=6):"
+ + "FD(timeout=3000):"
+ + "VERIFY_SUSPECT(timeout=1500):"
+ + "pbcast.NAKACK(gc_lag=10;retransmit_timeout=600,1200,2400,4800):"
+ + "pbcast.STABLE(desired_avg_gossip=10000):"
+ + "FRAG:"
+ + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
+ + "shun=true;print_local_addr=false)";
+ }
+
+ @Override
+ protected void shutdownExternal() throws Exception {
+ try {
+ if (adapter != null) {
+ adapter.stop();
+ }
+
+ channel.close();
+ }
+ finally {
+ adapter = null;
+ channel = null;
+ }
+ }
+
+ @Override
+ protected void sendExternalEvent(CayenneEvent localEvent) throws Exception {
+ Message message = new Message(null, null, eventToMessageObject(localEvent));
+ channel.send(message);
+ }
+
+ /**
+ * Converts CayenneEvent to a serializable object that will be sent via JMS. Default
+ * implementation simply returns the event, but subclasses can customize this
+ * behavior.
+ */
+ protected Serializable eventToMessageObject(CayenneEvent event) throws Exception {
+ return event;
+ }
+
+ /**
+ * Converts a Serializable instance to CayenneEvent. Returns null if the object is not
+ * supported. Default implementation simply tries to cast the object to CayenneEvent,
+ * but subclasses can customize this behavior.
+ */
+ protected CayenneEvent messageObjectToEvent(Serializable object) throws Exception {
+ return (object instanceof CayenneEvent) ? (CayenneEvent) object : null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeFactory.java b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeFactory.java
new file mode 100644
index 0000000..302e5ca
--- /dev/null
+++ b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeFactory.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Factory to create JavaGroupsBridge instances. If JavaGroups library is not installed
+ * this factory will return a noop EventBridge as a failover mechanism.
+ * <p/>
+ * For further information about JavaGroups consult the <a href="http://www.jgroups.org/">documentation</a>.
+ *
+ * @since 1.1
+ */
+public class JavaGroupsBridgeFactory implements EventBridgeFactory {
+
+ /**
+ * Creates a JavaGroupsBridge instance. Since JavaGroups is not shipped with Cayenne
+ * and should be installed separately, a common misconfiguration problem may be the
+ * absence of JavaGroups jar file. This factory returns a dummy noop EventBridge, if
+ * this is the case. This would allow the application to continue to run, but without
+ * remote notifications.
+ */
+ public EventBridge createEventBridge(
+ Collection<EventSubject> localSubjects,
+ String externalSubject,
+ Map<String, String> properties) {
+ return new JavaGroupsBridge(localSubjects, externalSubject, properties);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeProvider.java b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeProvider.java
new file mode 100644
index 0000000..983aa7f
--- /dev/null
+++ b/cayenne-jgroups/src/main/java/org/apache/cayenne/event/JavaGroupsBridgeProvider.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.access.DataDomain;
+import org.apache.cayenne.access.DataRowStore;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class JavaGroupsBridgeProvider implements Provider<EventBridge> {
+
+ @Inject
+ protected DataDomain dataDomain;
+
+ @Inject(JGroupsModule.JAVA_GROUPS_BRIDGE_PROPERTIES_MAP)
+ Map<String, String> properties;
+
+ @Override
+ public EventBridge get() throws DIRuntimeException {
+ EventSubject snapshotEventSubject = EventSubject.getSubject(DataRowStore.class, dataDomain.getName());
+
+ return new JavaGroupsBridge(
+ Collections.singleton(snapshotEventSubject),
+ EventBridge.convertToExternalSubject(snapshotEventSubject),
+ properties);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider b/cayenne-jgroups/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
new file mode 100644
index 0000000..b6c6632
--- /dev/null
+++ b/cayenne-jgroups/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
@@ -0,0 +1,20 @@
+##################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF 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.
+##################################################################
+
+org.apache.cayenne.event.JGroupsServerModuleProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/test/java/org/apache/cayenne/event/CayenneJGroupsModuleProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/test/java/org/apache/cayenne/event/CayenneJGroupsModuleProviderTest.java b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/CayenneJGroupsModuleProviderTest.java
new file mode 100644
index 0000000..320d490
--- /dev/null
+++ b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/CayenneJGroupsModuleProviderTest.java
@@ -0,0 +1,36 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.unit.util.ModuleProviderChecker;
+import org.junit.Test;
+
+/**
+ * @since 4.0
+ */
+public class CayenneJGroupsModuleProviderTest {
+
+ @Test
+ public void testAutoLoadable() {
+ ModuleProviderChecker.testProviderPresent(JGroupsServerModuleProvider.class, CayenneServerModuleProvider.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeFactoryTest.java b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeFactoryTest.java
new file mode 100644
index 0000000..694dc24
--- /dev/null
+++ b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeFactoryTest.java
@@ -0,0 +1,84 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ */
+public class JavaGroupsBridgeFactoryTest {
+
+ protected Collection<EventSubject> subjects = Collections.singleton(new EventSubject("test"));
+ protected String externalSubject = "subject";
+
+ @Test
+ public void testCreateEventBridge() throws Exception {
+ EventBridge bridge = new JavaGroupsBridgeFactory().createEventBridge(
+ subjects,
+ externalSubject,
+ Collections.<String, String>emptyMap());
+
+ assertNotNull(bridge);
+ assertTrue(bridge instanceof JavaGroupsBridge);
+ assertEquals(subjects, bridge.getLocalSubjects());
+ assertEquals(externalSubject, bridge.getExternalSubject());
+ }
+
+ @Test
+ public void testUseProperties() throws Exception {
+ JavaGroupsBridgeFactory bridgeFactory = new JavaGroupsBridgeFactory();
+
+ Map<String, String> properties = new HashMap<>();
+ properties.put(JavaGroupsBridge.MCAST_ADDRESS_PROPERTY, JavaGroupsBridgeProviderTest.MCAST_ADDRESS_TEST);
+ properties.put(JavaGroupsBridge.MCAST_PORT_PROPERTY, JavaGroupsBridgeProviderTest.MCAST_PORT_TEST);
+ properties.put(JavaGroupsBridge.JGROUPS_CONFIG_URL_PROPERTY, JavaGroupsBridgeProviderTest.CONFIG_URL_TEST);
+
+ JavaGroupsBridge bridge = (JavaGroupsBridge) bridgeFactory.createEventBridge(
+ subjects,
+ externalSubject,
+ properties);
+
+ assertEquals(bridge.getMulticastAddress(), JavaGroupsBridgeProviderTest.MCAST_ADDRESS_TEST);
+ assertEquals(bridge.getMulticastPort(), JavaGroupsBridgeProviderTest.MCAST_PORT_TEST);
+ assertEquals(bridge.getConfigURL(), JavaGroupsBridgeProviderTest.CONFIG_URL_TEST);
+ }
+
+ @Test
+ public void testUseDefaultProperties() throws Exception {
+ JavaGroupsBridgeFactory bridgeFactory = new JavaGroupsBridgeFactory();
+ JavaGroupsBridge bridge = (JavaGroupsBridge) bridgeFactory.createEventBridge(
+ subjects,
+ externalSubject,
+ Collections.<String, String>emptyMap());
+
+ assertEquals(bridge.getMulticastAddress(), JavaGroupsBridge.MCAST_ADDRESS_DEFAULT);
+ assertEquals(bridge.getMulticastPort(), JavaGroupsBridge.MCAST_PORT_DEFAULT);
+ assertEquals(bridge.getConfigURL(), null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeProviderTest.java b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeProviderTest.java
new file mode 100644
index 0000000..00232d4
--- /dev/null
+++ b/cayenne-jgroups/src/test/java/org/apache/cayenne/event/JavaGroupsBridgeProviderTest.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.access.DataDomain;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.DefaultRuntimeProperties;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.log.Slf4jJdbcEventLogger;
+import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.tx.DefaultTransactionFactory;
+import org.apache.cayenne.tx.DefaultTransactionManager;
+import org.apache.cayenne.tx.TransactionFactory;
+import org.apache.cayenne.tx.TransactionManager;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class JavaGroupsBridgeProviderTest {
+
+ private final DataDomain DOMAIN = new DataDomain("test");
+ private final EventManager EVENT_MANAGER = new DefaultEventManager();
+ protected static final String MCAST_ADDRESS_TEST = "192.168.0.0";
+ protected static final String MCAST_PORT_TEST = "1521";
+ protected static final String CONFIG_URL_TEST = "somehost.com";
+
+ @Test
+ public void testGetJavaGroupsBridge() throws Exception {
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JGroupsModule());
+ EventBridge bridge = injector.getInstance(EventBridge.class);
+
+ assertNotNull(bridge);
+ assertTrue(bridge instanceof JavaGroupsBridge);
+ }
+
+ @Test
+ public void testUseProperties() throws Exception {
+ Module module = binder -> {
+ JGroupsModule.contributeMulticastAddress(binder, MCAST_ADDRESS_TEST);
+ JGroupsModule.contributeMulticastPort(binder, Integer.parseInt(MCAST_PORT_TEST));
+ JGroupsModule.contributeConfigUrl(binder, CONFIG_URL_TEST);
+ };
+
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JGroupsModule(), module);
+ JavaGroupsBridge bridge = (JavaGroupsBridge) injector.getInstance(EventBridge.class);
+
+ assertEquals(MCAST_ADDRESS_TEST, bridge.getMulticastAddress());
+ assertEquals(MCAST_PORT_TEST, bridge.getMulticastPort());
+ assertEquals(CONFIG_URL_TEST, bridge.getConfigURL());
+ }
+
+ @Test
+ public void testUseDefaultProperties() throws Exception {
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JGroupsModule());
+ JavaGroupsBridge bridge = (JavaGroupsBridge) injector.getInstance(EventBridge.class);
+
+ assertEquals(JavaGroupsBridge.MCAST_ADDRESS_DEFAULT, bridge.getMulticastAddress());
+ assertEquals(JavaGroupsBridge.MCAST_PORT_DEFAULT, bridge.getMulticastPort());
+ assertEquals(null, bridge.getConfigURL());
+ }
+
+ class DefaultBindings implements Module {
+ @Override
+ public void configure(Binder binder) {
+ binder.bindMap(String.class, Constants.PROPERTIES_MAP);
+ binder.bind(DataDomain.class).toInstance(DOMAIN);
+ binder.bind(EventManager.class).toInstance(EVENT_MANAGER);
+ binder.bind(TransactionManager.class).to(DefaultTransactionManager.class);
+ binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class);
+ binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
+ binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-jms/pom.xml b/cayenne-jms/pom.xml
new file mode 100644
index 0000000..f4da57b
--- /dev/null
+++ b/cayenne-jms/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>cayenne-parent</artifactId>
+ <groupId>org.apache.cayenne</groupId>
+ <version>4.1.M2-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cayenne-jms</artifactId>
+ <name>cayenne-jms: Cayenne JMS Event bridge</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- This ensures LICENSE and NOTICE inclusion in all jars -->
+ <plugin>
+ <artifactId>maven-remote-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridge.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridge.java b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridge.java
new file mode 100644
index 0000000..0b746fc
--- /dev/null
+++ b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridge.java
@@ -0,0 +1,280 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.util.IDUtil;
+
+import javax.jms.Message;
+import javax.jms.MessageFormatException;
+import javax.jms.MessageListener;
+import javax.jms.ObjectMessage;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.jms.TopicConnection;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicPublisher;
+import javax.jms.TopicSession;
+import javax.jms.TopicSubscriber;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Implementation of EventBridge that passes and receives events via JMS (Java Messaging
+ * Service). JMSBridge uses "publish/subscribe" model for communication with external
+ * agents.
+ *
+ * @since 1.1
+ */
+public class JMSBridge extends EventBridge implements MessageListener {
+
+ // this is an OpenJMS default for the factory name. Likely it won't work with
+ // anything else
+ public static final String TOPIC_CONNECTION_FACTORY_DEFAULT = "JmsTopicConnectionFactory";
+
+ public static final String TOPIC_CONNECTION_FACTORY_PROPERTY = "cayenne.JMSBridge.topic.connection.factory";
+
+ static final String VM_ID = new String(IDUtil.pseudoUniqueByteSequence16());
+ static final String VM_ID_PROPERTY = "VM_ID";
+
+ protected String topicConnectionFactoryName;
+
+ protected TopicConnection sendConnection;
+ protected TopicSession sendSession;
+ protected TopicConnection receivedConnection;
+ protected TopicPublisher publisher;
+ protected TopicSubscriber subscriber;
+
+ public JMSBridge(EventSubject localSubject, String externalSubject) {
+ super(localSubject, externalSubject);
+ }
+
+ /**
+ * @since 1.2
+ */
+ public JMSBridge(Collection<EventSubject> localSubjects, String externalSubject) {
+ super(localSubjects, externalSubject);
+ }
+
+ /**
+ * @since 4.0
+ */
+ public JMSBridge(Collection<EventSubject> localSubjects, String externalSubject, Map<String, String> properties) {
+ super(localSubjects, externalSubject);
+
+ // configure properties
+ String topicConnectionFactory = properties
+ .get(TOPIC_CONNECTION_FACTORY_PROPERTY);
+
+ this.topicConnectionFactoryName = (topicConnectionFactory != null)
+ ? topicConnectionFactory
+ : TOPIC_CONNECTION_FACTORY_DEFAULT;
+ }
+
+ /**
+ * JMS MessageListener implementation. Injects received events to the EventManager
+ * local event queue.
+ */
+ public void onMessage(Message message) {
+
+ try {
+ Object vmID = message.getObjectProperty(JMSBridge.VM_ID_PROPERTY);
+ if (JMSBridge.VM_ID.equals(vmID)) {
+ return;
+ }
+
+ if (!(message instanceof ObjectMessage)) {
+ return;
+ }
+
+ ObjectMessage objectMessage = (ObjectMessage) message;
+ CayenneEvent event = messageObjectToEvent(objectMessage.getObject());
+ if (event != null) {
+ onExternalEvent(event);
+ }
+
+ }
+ catch (MessageFormatException mfex) {
+ // TODO: Andrus, 2/8/2006 logging... Log4J was removed to make this usable on
+ // the client
+ }
+ catch (Exception ex) {
+ // TODO: Andrus, 2/8/2006 logging... Log4J was removed to make this usable on
+ // the client
+ }
+ }
+
+ /**
+ * @return Name of javax.jms.TopicConnectionFactory accessible via JNDI.
+ */
+ public String getTopicConnectionFactoryName() {
+ return topicConnectionFactoryName;
+ }
+
+ public void setTopicConnectionFactoryName(String name) {
+ this.topicConnectionFactoryName = name;
+ }
+
+ /**
+ * Starts up JMS machinery for "publish/subscribe" model.
+ */
+ @Override
+ protected void startupExternal() throws Exception {
+ Context jndiContext = new InitialContext();
+ TopicConnectionFactory connectionFactory = (TopicConnectionFactory) jndiContext
+ .lookup(topicConnectionFactoryName);
+
+ Topic topic = null;
+
+ try {
+ topic = (Topic) jndiContext.lookup(externalSubject);
+ }
+ catch (NameNotFoundException ex) {
+ // can't find topic, try to create it
+ topic = topicNotFound(jndiContext, ex);
+
+ if (topic == null) {
+ throw ex;
+ }
+ }
+
+ // config publisher
+ if (receivesLocalEvents()) {
+ this.sendConnection = connectionFactory.createTopicConnection();
+ this.sendSession = sendConnection.createTopicSession(
+ false,
+ Session.AUTO_ACKNOWLEDGE);
+ this.publisher = sendSession.createPublisher(topic);
+ }
+
+ // config subscriber
+ if (receivesExternalEvents()) {
+ this.receivedConnection = connectionFactory.createTopicConnection();
+ this.subscriber = receivedConnection.createTopicSession(
+ false,
+ Session.AUTO_ACKNOWLEDGE).createSubscriber(topic);
+ this.subscriber.setMessageListener(this);
+ this.receivedConnection.start();
+ }
+ }
+
+ /**
+ * Attempts to create missing Topic. Since Topic creation is JMS-implementation
+ * specific, this task is left to subclasses. Current implementation simply rethrows
+ * the exception.
+ */
+ protected Topic topicNotFound(Context jndiContext, NamingException ex)
+ throws Exception {
+ throw ex;
+ }
+
+ /**
+ * Closes all resources used to communicate via JMS.
+ */
+ @Override
+ protected void shutdownExternal() throws Exception {
+ Exception lastException = null;
+
+ if (publisher != null) {
+ try {
+ publisher.close();
+ }
+ catch (Exception ex) {
+ lastException = ex;
+ }
+ }
+
+ if (subscriber != null) {
+ try {
+ subscriber.close();
+ }
+ catch (Exception ex) {
+ lastException = ex;
+ }
+ }
+
+ if (receivedConnection != null) {
+ try {
+ receivedConnection.close();
+ }
+ catch (Exception ex) {
+ lastException = ex;
+ }
+ }
+
+ if (sendSession != null) {
+ try {
+ sendSession.close();
+ }
+ catch (Exception ex) {
+ lastException = ex;
+ }
+ }
+
+ if (sendConnection != null) {
+ try {
+ sendConnection.close();
+ }
+ catch (Exception ex) {
+ lastException = ex;
+ }
+ }
+
+ publisher = null;
+ subscriber = null;
+ receivedConnection = null;
+ sendConnection = null;
+ sendSession = null;
+
+ if (lastException != null) {
+ throw lastException;
+ }
+ }
+
+ @Override
+ protected void sendExternalEvent(CayenneEvent localEvent) throws Exception {
+ ObjectMessage message = sendSession
+ .createObjectMessage(eventToMessageObject(localEvent));
+ message.setObjectProperty(JMSBridge.VM_ID_PROPERTY, JMSBridge.VM_ID);
+ publisher.publish(message);
+ }
+
+ /**
+ * Converts CayenneEvent to a serializable object that will be sent via JMS. Default
+ * implementation simply returns the event, but subclasses can customize this
+ * behavior.
+ */
+ protected Serializable eventToMessageObject(CayenneEvent event) throws Exception {
+ return event;
+ }
+
+ /**
+ * Converts a Serializable instance to CayenneEvent. Returns null if the object is not
+ * supported. Default implementation simply tries to cast the object to CayenneEvent,
+ * but subclasses can customize this behavior.
+ */
+ protected CayenneEvent messageObjectToEvent(Serializable object) throws Exception {
+ return (object instanceof CayenneEvent) ? (CayenneEvent) object : null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeFactory.java b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeFactory.java
new file mode 100644
index 0000000..b7772d8
--- /dev/null
+++ b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeFactory.java
@@ -0,0 +1,39 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Factory to create JMSBridge instances.
+ *
+ * @since 1.1
+ */
+public class JMSBridgeFactory implements EventBridgeFactory {
+
+ /**
+ * @since 1.2
+ */
+ public EventBridge createEventBridge(Collection<EventSubject> localSubjects, String externalSubject, Map<String, String> properties) {
+ return new JMSBridge(localSubjects, externalSubject, properties);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeProvider.java b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeProvider.java
new file mode 100644
index 0000000..6a06faa
--- /dev/null
+++ b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSBridgeProvider.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.access.DataDomain;
+import org.apache.cayenne.access.DataRowStore;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class JMSBridgeProvider implements Provider<EventBridge> {
+
+ @Inject
+ protected DataDomain dataDomain;
+
+ @Inject(JMSModule.JMS_BRIDGE_PROPERTIES_MAP)
+ Map<String, String> properties;
+
+ @Override
+ public EventBridge get() throws DIRuntimeException {
+ EventSubject snapshotEventSubject = EventSubject.getSubject(DataRowStore.class, dataDomain.getName());
+
+ return new JMSBridge(
+ Collections.singleton(snapshotEventSubject),
+ EventBridge.convertToExternalSubject(snapshotEventSubject),
+ properties);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSModule.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSModule.java b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSModule.java
new file mode 100644
index 0000000..b532bc5
--- /dev/null
+++ b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSModule.java
@@ -0,0 +1,54 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.MapBuilder;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 4.0
+ */
+public class JMSModule implements Module {
+
+ /**
+ * A DI container key for the Map<String, String> storing
+ * {@link org.apache.cayenne.event.JMSBridge} properties
+ *
+ * @since 4.0
+ */
+ public static final String JMS_BRIDGE_PROPERTIES_MAP = "cayenne.server.jms_bridge";
+
+ public static void contributeTopicConnectionFactory(Binder binder, String factory) {
+ contributeProperties(binder).put(JMSBridge.TOPIC_CONNECTION_FACTORY_PROPERTY, factory);
+ }
+
+ private static MapBuilder<String> contributeProperties(Binder binder) {
+ return binder.bindMap(String.class, JMS_BRIDGE_PROPERTIES_MAP);
+ }
+
+ @Override
+ public void configure(Binder binder) {
+ // init properties' defaults
+ contributeTopicConnectionFactory(binder, JMSBridge.TOPIC_CONNECTION_FACTORY_DEFAULT);
+
+ binder.bind(EventBridge.class).toProvider(JMSBridgeProvider.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSServerModuleProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSServerModuleProvider.java b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSServerModuleProvider.java
new file mode 100644
index 0000000..6979d21
--- /dev/null
+++ b/cayenne-jms/src/main/java/org/apache/cayenne/event/JMSServerModuleProvider.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 4.0
+ */
+public class JMSServerModuleProvider implements CayenneServerModuleProvider {
+
+ @Override
+ public Module module() {
+ return new JMSModule();
+ }
+
+ @Override
+ public Class<? extends Module> moduleType() {
+ return JMSModule.class;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Collection<Class<? extends Module>> overrides() {
+ Collection modules = Collections.singletonList(ServerModule.class);
+ return modules;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider b/cayenne-jms/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
new file mode 100644
index 0000000..7c54e3f
--- /dev/null
+++ b/cayenne-jms/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
@@ -0,0 +1,20 @@
+##################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF 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.
+##################################################################
+
+org.apache.cayenne.event.JMSServerModuleProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/test/java/org/apache/cayenne/event/CayenneJMSModuleProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/test/java/org/apache/cayenne/event/CayenneJMSModuleProviderTest.java b/cayenne-jms/src/test/java/org/apache/cayenne/event/CayenneJMSModuleProviderTest.java
new file mode 100644
index 0000000..3b3e87a
--- /dev/null
+++ b/cayenne-jms/src/test/java/org/apache/cayenne/event/CayenneJMSModuleProviderTest.java
@@ -0,0 +1,36 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.unit.util.ModuleProviderChecker;
+import org.junit.Test;
+
+/**
+ * @since 4.0
+ */
+public class CayenneJMSModuleProviderTest {
+
+ @Test
+ public void testAutoLoadable() {
+ ModuleProviderChecker.testProviderPresent(JMSServerModuleProvider.class, CayenneServerModuleProvider.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeFactoryTest.java b/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeFactoryTest.java
new file mode 100644
index 0000000..1e50145
--- /dev/null
+++ b/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeFactoryTest.java
@@ -0,0 +1,77 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class JMSBridgeFactoryTest {
+
+ protected Collection<EventSubject> subjects = Collections.singleton(new EventSubject("test"));
+ protected String externalSubject = "subject";
+
+ @Test
+ public void testCreateEventBridge() throws Exception {
+ EventBridge bridge = new JMSBridgeFactory().createEventBridge(
+ subjects,
+ externalSubject,
+ Collections.<String, String>emptyMap());
+
+ assertNotNull(bridge);
+ assertTrue(bridge instanceof JMSBridge);
+ assertEquals(subjects, bridge.getLocalSubjects());
+ assertEquals(externalSubject, bridge.getExternalSubject());
+ }
+
+ @Test
+ public void testUseProperties() throws Exception {
+ JMSBridgeFactory bridgeFactory = new JMSBridgeFactory();
+
+ Map<String, String> properties = new HashMap<>();
+ properties.put(JMSBridge.TOPIC_CONNECTION_FACTORY_PROPERTY, JMSBridgeProviderTest.TOPIC_CONNECTION_FACTORY_TEST);
+
+ JMSBridge bridge = (JMSBridge) bridgeFactory.createEventBridge(
+ subjects,
+ externalSubject,
+ properties);
+
+ assertEquals(bridge.getTopicConnectionFactoryName(), JMSBridgeProviderTest.TOPIC_CONNECTION_FACTORY_TEST);
+ }
+
+ @Test
+ public void testUseDefaultProperties() throws Exception {
+ JMSBridgeFactory bridgeFactory = new JMSBridgeFactory();
+ JMSBridge bridge = (JMSBridge) bridgeFactory.createEventBridge(
+ subjects,
+ externalSubject,
+ Collections.<String, String>emptyMap());
+
+ assertEquals(bridge.getTopicConnectionFactoryName(), JMSBridge.TOPIC_CONNECTION_FACTORY_DEFAULT);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeProviderTest.java b/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeProviderTest.java
new file mode 100644
index 0000000..83404eb
--- /dev/null
+++ b/cayenne-jms/src/test/java/org/apache/cayenne/event/JMSBridgeProviderTest.java
@@ -0,0 +1,87 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.cayenne.event;
+
+import org.apache.cayenne.access.DataDomain;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.DefaultRuntimeProperties;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.log.Slf4jJdbcEventLogger;
+import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.tx.DefaultTransactionFactory;
+import org.apache.cayenne.tx.DefaultTransactionManager;
+import org.apache.cayenne.tx.TransactionFactory;
+import org.apache.cayenne.tx.TransactionManager;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class JMSBridgeProviderTest {
+
+ private final DataDomain DOMAIN = new DataDomain("test");
+ private final EventManager EVENT_MANAGER = new DefaultEventManager();
+ protected static final String TOPIC_CONNECTION_FACTORY_TEST = "SomeTopicConnectionFactory";
+
+ @Test
+ public void testGetJMSBridge() throws Exception {
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JMSModule());
+ EventBridge bridge = injector.getInstance(EventBridge.class);
+
+ assertNotNull(bridge);
+ assertTrue(bridge instanceof JMSBridge);
+ }
+
+ @Test
+ public void testUseProperties() {
+ Module module = binder -> JMSModule.contributeTopicConnectionFactory(binder, TOPIC_CONNECTION_FACTORY_TEST);
+
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JMSModule(), module);
+ JMSBridge bridge = (JMSBridge) injector.getInstance(EventBridge.class);
+
+ assertEquals(TOPIC_CONNECTION_FACTORY_TEST, bridge.getTopicConnectionFactoryName());
+ }
+
+ @Test
+ public void testUseDefaultProperties() throws Exception {
+ Injector injector = DIBootstrap.createInjector(new DefaultBindings(), new JMSModule());
+ JMSBridge bridge = (JMSBridge) injector.getInstance(EventBridge.class);
+
+ assertEquals(JMSBridge.TOPIC_CONNECTION_FACTORY_DEFAULT, bridge.getTopicConnectionFactoryName());
+ }
+
+ class DefaultBindings implements Module {
+ @Override
+ public void configure(Binder binder) {
+ binder.bindMap(String.class, Constants.PROPERTIES_MAP);
+ binder.bind(DataDomain.class).toInstance(DOMAIN);
+ binder.bind(EventManager.class).toInstance(EVENT_MANAGER);
+ binder.bind(TransactionManager.class).to(DefaultTransactionManager.class);
+ binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class);
+ binder.bind(JdbcEventLogger.class).to(Slf4jJdbcEventLogger.class);
+ binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ab1fd0bf/cayenne-xmpp/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-xmpp/pom.xml b/cayenne-xmpp/pom.xml
new file mode 100644
index 0000000..cf3f849
--- /dev/null
+++ b/cayenne-xmpp/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>cayenne-parent</artifactId>
+ <groupId>org.apache.cayenne</groupId>
+ <version>4.1.M2-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cayenne-xmpp</artifactId>
+ <name>cayenne-xmpp: Cayenne XMPP Event bridge</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>jivesoftware</groupId>
+ <artifactId>smack</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>jivesoftware</groupId>
+ <artifactId>smackx</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- This ensures LICENSE and NOTICE inclusion in all jars -->
+ <plugin>
+ <artifactId>maven-remote-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file