/******************************************************************************* * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0, which accompanies this distribution * and is available at http://www.eclipse.org/legal/epl-v10.html. * * Contributors: * Oracle - initial design and implementation ******************************************************************************/ package org.eclipse.persistence.sessions.coordination.jgroups; import java.util.Map; import org.eclipse.persistence.exceptions.RemoteCommandManagerException; import org.eclipse.persistence.internal.sessions.coordination.RemoteConnection; import org.eclipse.persistence.internal.sessions.coordination.jgroups.JGroupsRemoteConnection; import org.eclipse.persistence.sessions.coordination.broadcast.BroadcastTransportManager; import org.eclipse.persistence.sessions.coordination.RemoteCommandManager; import org.jgroups.JChannel; /** * <p> * <b>Purpose</b>: Provide a transport implementation for the Remote Command Module (RCM) that publishes * to a JGroup channel. * <p> * JGroups is a library for distributed communications. * <p> * If issues are encountered with the default setting try,<br> * -Djava.net.preferIPv4Stack=true * <p> * @author James Sutherland * @since EclipseLink 2.6 */ public class JGroupsTransportManager extends BroadcastTransportManager { protected String configFile = ""; /** * PUBLIC: * Creates a JGroupsTransportManager. */ public JGroupsTransportManager() { } /** * PUBLIC: * Creates a JGroupsTransportManager. */ public JGroupsTransportManager(RemoteCommandManager rcm) { super(rcm); } /** * INTERNAL: * This method creates JGroupsRemoteConnection to be used by this TransportManager. * It uses a JGroups JChannel using the RCM channel name and specified (or defaulted) config file. * Channel is set to not receive own messages. */ protected JGroupsRemoteConnection createConnection(boolean isLocalConnectionBeingCreated) throws RemoteCommandManagerException { try { JChannel channel; if (configFile != null && !configFile.isEmpty()) { channel = new JChannel(configFile); } else { channel = new JChannel(); } channel.connect(this.rcm.getChannel()); channel.setDiscardOwnMessages(true); return new JGroupsRemoteConnection(this.rcm, channel, isLocalConnectionBeingCreated); } catch (Exception ex) { throw RemoteCommandManagerException.errorCreatingJGroupsConnection(this.configFile, ex); } } /** * INTERNAL: * JGroups does not require a DiscoveryManager, therefore * this method is called during RCM initialization to create all the necessary connections. */ @Override public void createConnections() { createLocalConnection(); createExternalConnection(); } /** * INTERNAL: * JGroups only has a single connection. * Verify there are no external connections, use the local connection as the external connection. */ public void createExternalConnection() { synchronized (this.connectionsToExternalServices) { if (this.connectionsToExternalServices.isEmpty()) { try { this.connectionsToExternalServices.put(this.rcm.getServiceId().getId(), this.localConnection); } catch (RemoteCommandManagerException rcmException) { // to recover handle RemoteCommandManagerException.ERROR_CREATING_JMS_CONNECTION: // after changing something (for instance config) // call createExternalConnection method again. rcm.handleException(rcmException); } } } } /** * INTERNAL: * JGroups only requires a single connection. * In case the local connection doesn't exist, this method creates it. */ @Override public synchronized void createLocalConnection() { if (this.localConnection == null) { try { this.localConnection = createConnection(true); } catch (RemoteCommandManagerException rcmException) { // to recover handle RemoteCommandManagerException.ERROR_CREATING_LOCAL_JMS_CONNECTION: // after changing something (for instance jmsHostUrl) // call createLocalConnection method again. rcm.handleException(rcmException); } } } /** * INTERNAL: * In case there's no external connection attempts to create one. * Returns external connections (only a single connection for JGroups). */ @Override public Map<String, RemoteConnection> getConnectionsToExternalServicesForCommandPropagation() { if (getConnectionsToExternalServices().isEmpty() && !this.rcm.isStopped()) { createExternalConnection(); } return super.getConnectionsToExternalServicesForCommandPropagation(); } /** * INTERNAL: * No-op, as the local connection does not need to be removed as JGroups manages registration. */ @Override public void removeLocalConnection() {} /** * PUBLIC: * Return the JGroups config xml file name. */ public String getConfigFile() { return configFile; } /** * PUBLIC: * Set the JGroups config xml file name. */ @Deprecated public void setConfigFile(String configFile) { this.configFile = configFile; } @Override public void setConfig(String config) { configFile = config; } }