All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.netty.channel.ChannelHandler Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS 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).

There is a newer version: 33.0.2.Final
Show newest version
/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project 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 io.netty.channel;

import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Handles or intercepts a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation, and forwards it
 * to the next handler in a {@link ChannelPipeline}.
 *
 * 

Sub-types

*

* {@link ChannelHandler} itself does not provide many methods. To handle a * a {@link ChannelInboundInvoker} or {@link ChannelOutboundInvoker} operation * you need to implement its sub-interfaces. There are many different sub-interfaces * which handles inbound and outbound operations. * * But the most useful for developers may be: *

    *
  • {@link ChannelInboundHandlerAdapter} handles and intercepts inbound operations
  • *
  • {@link ChannelOutboundHandlerAdapter} handles and intercepts outbound operations
  • *
* * You will also find more detailed explanation from the documentation of * each sub-interface on how an event is interpreted when it goes upstream and * downstream respectively. * *

The context object

*

* A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext} * object. A {@link ChannelHandler} is supposed to interact with the * {@link ChannelPipeline} it belongs to via a context object. Using the * context object, the {@link ChannelHandler} can pass events upstream or * downstream, modify the pipeline dynamically, or store the information * (using {@link AttributeKey}s) which is specific to the handler. * *

State management

* * A {@link ChannelHandler} often needs to store some stateful information. * The simplest and recommended approach is to use member variables: *
 * public interface Message {
 *     // your methods here
 * }
 *
 * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
 *
 *     private boolean loggedIn;
 *
 *     {@code @Override}
 *     public void channelRead0({@link ChannelHandlerContext} ctx, Message message) {
 *         {@link Channel} ch = e.getChannel();
 *         if (message instanceof LoginMessage) {
 *             authenticate((LoginMessage) message);
 *             loggedIn = true;
 *         } else (message instanceof GetDataMessage) {
 *             if (loggedIn) {
 *                 ch.write(fetchSecret((GetDataMessage) message));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 * 
* Because the handler instance has a state variable which is dedicated to * one connection, you have to create a new handler instance for each new * channel to avoid a race condition where a unauthenticated client can get * the confidential information: *
 * // Create a new handler instance per channel.
 * // See {@link ChannelInitializer#initChannel(Channel)}.
 * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
 *     {@code @Override}
 *     public void initChannel({@link Channel} channel) {
 *         channel.pipeline().addLast("handler", new DataServerHandler());
 *     }
 * }
 *
 * 
* *

Using {@link AttributeKey}

* * Although it's recommended to use member variables to store the state of a * handler, for some reason you might not want to create many handler instances. * In such a case, you can use {@link AttributeKey}s which is provided by * {@link ChannelHandlerContext}: *
 * public interface Message {
 *     // your methods here
 * }
 *
 * {@code @Sharable}
 * public class DataServerHandler extends {@link SimpleChannelInboundHandler}<Message> {
 *     private final {@link AttributeKey}<{@link Boolean}> auth =
 *           {@link AttributeKey#valueOf(String) AttributeKey.valueOf("auth")};
 *
 *     {@code @Override}
 *     public void channelRead({@link ChannelHandlerContext} ctx, Message message) {
 *         {@link Attribute}<{@link Boolean}> attr = ctx.attr(auth);
 *         {@link Channel} ch = ctx.channel();
 *         if (message instanceof LoginMessage) {
 *             authenticate((LoginMessage) o);
 *             attr.set(true);
 *         } else (message instanceof GetDataMessage) {
 *             if (Boolean.TRUE.equals(attr.get())) {
 *                 ch.write(fetchSecret((GetDataMessage) o));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 * 
* Now that the state of the handler isattached to the {@link ChannelHandlerContext}, you can add the * same handler instance to different pipelines: *
 * public class DataServerInitializer extends {@link ChannelInitializer}<{@link Channel}> {
 *
 *     private static final DataServerHandler SHARED = new DataServerHandler();
 *
 *     {@code @Override}
 *     public void initChannel({@link Channel} channel) {
 *         channel.pipeline().addLast("handler", SHARED);
 *     }
 * }
 * 
* * *

The {@code @Sharable} annotation

*

* In the example above which used an {@link AttributeKey}, * you might have noticed the {@code @Sharable} annotation. *

* If a {@link ChannelHandler} is annotated with the {@code @Sharable} * annotation, it means you can create an instance of the handler just once and * add it to one or more {@link ChannelPipeline}s multiple times without * a race condition. *

* If this annotation is not specified, you have to create a new handler * instance every time you add it to a pipeline because it has unshared state * such as member variables. *

* This annotation is provided for documentation purpose, just like * the JCIP annotations. * *

Additional resources worth reading

*

* Please refer to the {@link ChannelHandler}, and * {@link ChannelPipeline} to find out more about inbound and outbound operations, * what fundamental differences they have, how they flow in a pipeline, and how to handle * the operation in your application. */ public interface ChannelHandler { /** * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events. */ void handlerAdded(ChannelHandlerContext ctx) throws Exception; /** * Gets called after the {@link ChannelHandler} was removed from the actual context and it doesn't handle events * anymore. */ void handlerRemoved(ChannelHandlerContext ctx) throws Exception; /** * Gets called if a {@link Throwable} was thrown. */ void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; /** * Indicates that the same instance of the annotated {@link ChannelHandler} * can be added to one or more {@link ChannelPipeline}s multiple times * without a race condition. *

* If this annotation is not specified, you have to create a new handler * instance every time you add it to a pipeline because it has unshared * state such as member variables. *

* This annotation is provided for documentation purpose, just like * the JCIP annotations. */ @Inherited @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Sharable { // no value } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy