Allow to bind a client channel in a seperate step. This can be useful if you want to pass an object on connect to your handlers. Kind of related to #275

This commit is contained in:
norman 2012-05-22 13:35:20 +02:00
parent 5f28d01507
commit 9024bc8704
3 changed files with 88 additions and 0 deletions

View File

@ -229,4 +229,69 @@ public class ClientBootstrap extends Bootstrap {
// Connect.
return ch.connect(remoteAddress);
}
/**
* Attempts to bind a channel with the specified {@code localAddress}. later the channel can be connected
* to a remoteAddress by calling {@link Channel#connect(SocketAddress)}.This method is useful where bind and connect
* need to be done in separate steps.
*
* This can also be useful if you want to set and attachment to the {@link Channel} via
* {@link Channel#setAttachment(Object)} so you can use it after the {@link #bind(SocketAddress)} was done.
* <br>
* For example:
*
* <pre>
* ChannelFuture bindFuture = boostrap.bind(new InetSocketAddress("192.168.0.15", 0));
* Channel channel = bindFuture.getChannel();
* channel.setAttachment(dataObj);
* boostrap.connect(new InetSocketAddress("192.168.0.30", 8080));
* </pre>
* <br>
*
* You can use it then in your handlers like this:
*
* <pre>
* public class YourHandler extends SimpleChannelUpstreamHandler {
* public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
* Object dataObject = ctx.getChannel().getAttachement();
* }
* }
*
* </pre>
*
* @return a future object which notifies when this bind attempt
* succeeds or fails
*
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture bind(final SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
// Set the options.
Channel ch = getFactory().newChannel(pipeline);
boolean success = false;
try {
ch.getConfig().setOptions(getOptions());
success = true;
} finally {
if (!success) {
ch.close();
}
}
// Bind.
return ch.bind(localAddress);
}
}

View File

@ -53,6 +53,7 @@ public abstract class AbstractChannel implements Channel {
/** Cache for the string representation of this channel */
private boolean strValConnected;
private String strVal;
private volatile Object attachment;
/**
* Creates a new instance.
@ -249,6 +250,13 @@ public abstract class AbstractChannel implements Channel {
return Channels.write(this, message, remoteAddress);
}
public Object getAttachment() {
return attachment;
}
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
/**
* Returns the {@link String} representation of this channel. The returned
* string contains the {@linkplain #getId() ID}, {@linkplain #getLocalAddress() local address},

View File

@ -359,4 +359,19 @@ public interface Channel extends Comparable<Channel> {
* {@code interestOps} change request succeeds or fails
*/
ChannelFuture setReadable(boolean readable);
/**
* Retrieves an object which is {@link #setAttachment(Object) attached} to
* this {@link Channel}.
*
* @return {@code null} if no object was attached or {@code null} was
* attached
*/
Object getAttachment();
/**
* Attaches an object to this {@link Channel} to store a stateful
* information
*/
void setAttachment(Object attachment);
}