Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ejb.client.remoting;
import static org.jboss.ejb.client.remoting.Protocol.*;
import static org.xnio.IoUtils.safeClose;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
import org.jboss.ejb.client.AttachmentKeys;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientInvocationContext;
import org.jboss.ejb.client.EJBLocator;
import org.jboss.ejb.client.EJBReceiver;
import org.jboss.ejb.client.EJBReceiverContext;
import org.jboss.ejb.client.EJBReceiverInvocationContext;
import org.jboss.ejb.client.Logs;
import org.jboss.ejb.client.RequestSendFailedException;
import java.rmi.UnmarshalException;
import org.jboss.ejb.client.StatefulEJBLocator;
import org.jboss.ejb.client.TransactionID;
import org.jboss.ejb.client.annotation.CompressionHint;
import org.jboss.logging.Logger;
import org.jboss.marshalling.ByteOutput;
import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.remoting3.Channel;
import org.jboss.remoting3.CloseHandler;
import org.jboss.remoting3.Connection;
import org.jboss.remoting3.MessageOutputStream;
import org.xnio.IoFuture;
import org.xnio.IoUtils;
import org.xnio.OptionMap;
/**
* A {@link EJBReceiver} which uses JBoss Remoting to communicate with the server for EJB invocations
*
* @author David M. Lloyd
*/
public final class RemotingConnectionEJBReceiver extends EJBReceiver {
public static final String REMOTE = "remote";
public static final String HTTP_REMOTING = "http-remoting";
public static final String HTTPS_REMOTING = "https-remoting";
private static final Logger logger = Logger.getLogger(RemotingConnectionEJBReceiver.class);
private static final String EJB_CHANNEL_NAME = "jboss.ejb";
private final Connection connection;
private final Map channelAssociations = new IdentityHashMap();
/**
* A latch which will be used to wait for the initial module availability report from the server
* after the version handshake between the server and the client is successfully completed.
*/
private final Map moduleAvailabilityReportLatches = new IdentityHashMap();
private final MarshallerFactory marshallerFactory;
private final ReconnectHandler reconnectHandler;
private final OptionMap channelCreationOptions;
private final String remotingProtocol;
private static final Logs log = Logs.MAIN;
/**
* Construct a new instance.
*
* @param connection the connection to associate with
* @param remotingProtocol the remoting protocol in use
*/
public RemotingConnectionEJBReceiver(final Connection connection, final String remotingProtocol) {
this(connection, null, OptionMap.EMPTY, remotingProtocol);
}
/**
* Construct a new instance.
*
* @param connection the connection to associate with
* @deprecated Since 2.0.0. Use {@link #RemotingConnectionEJBReceiver(org.jboss.remoting3.Connection, String)} instead
*/
@Deprecated
public RemotingConnectionEJBReceiver(final Connection connection) {
this(connection, HTTP_REMOTING);
}
/**
* Construct a new instance.
*
* @param connection the connection to associate with
* @param reconnectHandler The {@link org.jboss.ejb.client.remoting.ReconnectHandler} to use when the connection breaks
* @param channelCreationOptions The {@link org.xnio.OptionMap options} to be used during channel creation
* @deprecated Since 2.0.0. Use {@link #RemotingConnectionEJBReceiver(org.jboss.remoting3.Connection, ReconnectHandler, org.xnio.OptionMap, String)} instead
*/
@Deprecated
public RemotingConnectionEJBReceiver(final Connection connection, final ReconnectHandler reconnectHandler, final OptionMap channelCreationOptions) {
this(connection, reconnectHandler, channelCreationOptions, HTTP_REMOTING);
}
/**
* Construct a new instance.
*
* @param connection the connection to associate with
* @param reconnectHandler The {@link org.jboss.ejb.client.remoting.ReconnectHandler} to use when the connection breaks
* @param channelCreationOptions The {@link org.xnio.OptionMap options} to be used during channel creation
* @param remotingProtocol
*/
public RemotingConnectionEJBReceiver(final Connection connection, final ReconnectHandler reconnectHandler, final OptionMap channelCreationOptions, final String remotingProtocol) {
super(connection.getRemoteEndpointName());
this.connection = connection;
this.reconnectHandler = reconnectHandler;
this.remotingProtocol = remotingProtocol;
this.channelCreationOptions = channelCreationOptions == null ? OptionMap.EMPTY : channelCreationOptions;
this.marshallerFactory = Marshalling.getProvidedMarshallerFactory("river");
if (this.marshallerFactory == null) {
throw new RuntimeException("Could not find a marshaller factory for 'river' marshalling strategy");
}
}
@Override
public void associate(final EJBReceiverContext context) {
// a latch for waiting a version handshake
final CountDownLatch versionHandshakeLatch = new CountDownLatch(1);
// setup a latch which will be used for waiting initial module availability report from the server
final CountDownLatch initialModuleAvailabilityLatch = new CountDownLatch(1);
synchronized (this.moduleAvailabilityReportLatches) {
this.moduleAvailabilityReportLatches.put(context, initialModuleAvailabilityLatch);
}
final VersionReceiver versionReceiver = new VersionReceiver(versionHandshakeLatch);
final IoFuture futureChannel = connection.openChannel(EJB_CHANNEL_NAME, this.channelCreationOptions);
futureChannel.addNotifier(new IoFuture.HandlingNotifier() {
public void handleCancelled(final EJBReceiverContext context) {
logger.debugf("Channel open requested cancelled for context %s", context);
context.close();
}
public void handleFailed(final IOException exception, final EJBReceiverContext context) {
logger.error("Failed to open channel for context " + context, exception);
context.close();
}
public void handleDone(final Channel channel, final EJBReceiverContext context) {
channel.addCloseHandler(new CloseHandler() {
public void handleClose(final Channel closed, final IOException exception) {
logger.debugf(exception, "Closing channel%s", closed);
context.close();
}
});
logger.debugf("Channel %s opened for context %s Waiting for version handshake message from server", channel, context);
// receive version message from server
channel.receiveMessage(versionReceiver);
}
}, context);
boolean successfulHandshake = false;
try {
// wait for the handshake to complete
// The time to "wait" for the handshake to complete is the same as the invocation timeout
// set in this EJB client context's configuration, since a handshake is essentially a request
// followed for a wait for the response
final EJBClientConfiguration ejbClientConfiguration = context.getClientContext().getEJBClientConfiguration();
final long versionHandshakeTimeoutInMillis;
if (ejbClientConfiguration == null || ejbClientConfiguration.getInvocationTimeout() <= 0) {
// default to 5000 milli sec
versionHandshakeTimeoutInMillis = 5000;
} else {
versionHandshakeTimeoutInMillis = ejbClientConfiguration.getInvocationTimeout();
}
successfulHandshake = versionHandshakeLatch.await(versionHandshakeTimeoutInMillis, TimeUnit.MILLISECONDS);
if (successfulHandshake) {
final Channel compatibleChannel = versionReceiver.getCompatibleChannel();
final ChannelAssociation channelAssociation = new ChannelAssociation(this, context, compatibleChannel, (byte) versionReceiver.getNegotiatedProtocolVersion(), this.marshallerFactory, this.reconnectHandler, remotingProtocol);
synchronized (this.channelAssociations) {
this.channelAssociations.put(context, channelAssociation);
}
Logs.REMOTING.successfulVersionHandshake(context, compatibleChannel);
} else {
// no version handshake done. close the context
Logs.REMOTING.versionHandshakeNotCompleted(context);
context.close();
// register reconnect handler for retries due to e.g. timeouts
if (this.reconnectHandler != null) {
//only add the reconnect handler if the version handshake did not fail due to an incompatibility
// (latch is not being counted down on failure)
if (!versionReceiver.failedCompatibility()) {
logger.debugf("Adding reconnect handler to client context %s", context.getClientContext());
context.getClientContext().registerReconnectHandler(this.reconnectHandler);
}
}
}
} catch (InterruptedException e) {
context.close();
}
if (successfulHandshake) {
// Now that the version handshake has been completed, let's await the initial module report
// from the server. This initial wait is necessary to ensure that any immediate invocation on the receiver
// doesn't fail due to non-availability of the module report (which effectively means this receiver won't
// know whether it can handle an invocation on a appname/modulename/distinctname combination
try {
final boolean initialReportAvailable = initialModuleAvailabilityLatch.await(5, TimeUnit.SECONDS);
if (!initialReportAvailable) {
// let's log a message and just return back. Don't close the context since it's *not* an error
// that the module report wasn't available in that amount of time.
Logs.REMOTING.initialModuleAvailabilityReportNotReceived(this);
}
} catch (InterruptedException e) {
logger.debugf(e, "Caught InterruptedException while waiting for initial module availability report for %s", this);
}
}
}
@Override
public void disassociate(final EJBReceiverContext context) {
ChannelAssociation channelAssociation = null;
synchronized (this.channelAssociations) {
channelAssociation = this.channelAssociations.remove(context);
}
// close the channel that is associated
if(channelAssociation != null) {
try {
channelAssociation.getChannel().close();
} catch(IOException e) {
logger.warn("Caught IOException when trying to close channel: " + channelAssociation.getChannel(), e);
}
}
}
@Override
public void processInvocation(final EJBClientInvocationContext clientInvocationContext, final EJBReceiverInvocationContext ejbReceiverInvocationContext) throws Exception {
if(System.getSecurityManager() == null) {
processInvocationInternal(clientInvocationContext, ejbReceiverInvocationContext);
} else {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction