blob: 5f6a6f5d6af71a3585379d864ea0332db5bbfc84 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// cdelahun - Bug 214534: added JMS Cache Coordination for publishing only
package org.eclipse.persistence.sessions.coordination.jms;
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.jms.JMSTopicRemoteConnection;
import org.eclipse.persistence.sessions.coordination.RemoteCommandManager;
/**
* <p>
* <b>Purpose</b>: Provide a transport implementation for the Remote Command Module (RCM) that both publishes
* and subscribes to a JMS topic.
* </p><p>
* <b>Description</b>: This class manages two connections to the same known JMS Topic:
* external connection for publishing, local connection for receiving messages.
* </p>
* @author Steven Vo
* @since OracleAS TopLink 10<i>g</i> (10.0.3)
*/
public class JMSTopicTransportManager extends JMSPublishingTransportManager {
public JMSTopicTransportManager(RemoteCommandManager rcm) {
super(rcm);
}
/**
* INTERNAL:
* JMSTopicTransportManager may have only two connections: one local and one external.
* In case the local connection doesn't exist, this method creates it.
*/
@Override
public synchronized void createLocalConnection() {
if(localConnection == null) {
try {
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,
* if that's successful then (in case there is no local connection, too)
* attempts to create local connection in a separate thread.
* Returns clone of the original map.
*/
@Override
public Map<String, RemoteConnection> getConnectionsToExternalServicesForCommandPropagation() {
if (this.localConnection == null && !this.rcm.isStopped()) {
// It's a good time to create localConnection,
// in a new thread - to return externalConnections promptly.
this.rcm.getServerPlatform().launchContainerRunnable(new Runnable() {
@Override
public void run() {
try {
createLocalConnection();
} catch (RemoteCommandManagerException ex) {
// Ignore exception - user had a chance to handle it in createLocalConnection method:
// for instance to change host url and create a new local connection.
}
}
});
}
return super.getConnectionsToExternalServicesForCommandPropagation();
}
/**
* INTERNAL:
* caches local connection, set localConnection to null, closes the cached connection in a new thread.
*/
@Override
public void removeLocalConnection() {
JMSTopicRemoteConnection connectionToRemove = (JMSTopicRemoteConnection)localConnection;
synchronized(this) {
if(connectionToRemove == localConnection) {
localConnection = null;
} else {
connectionToRemove = null;
}
}
// closing connection may take time - do it outside of the synchronized block
if(connectionToRemove != null) {
connectionToRemove.close();
}
}
}