I've used the all-in-one jar from Netty, but MessageEvent cannot be resolved:
import io.netty.channel.MessageEvent;
GameServer.java
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new GameServerHandler());
ch.pipeline().addLast("protobufHandler", new MessagesHandler());
}
Also, if I remove the MessageEvent to make it work, I can't override it.
public class MessageHandler extends SimpleChannelInboundHandler<Object> {
#Override
public void messageReceived(ChannelHandlerContext arg0, MessageEvent msg) {
// Print msg
}
}
I'm using the latest release, what I'm doing wrong?
There is no class called MessageEvent in Netty 4. I think you want to replace MessageEvent with Object in your MessageHandler.
Related
Netty TCP Server is running at port 8000 receiving NMEA format data. It uses Marine API library to convert the gibberish to a meaningful information which needs input stream from the socket.
SentenceReader sentenceReader = new SentenceReader(socket.getInputStream());
sentenceReader.addSentenceListener(new MultiSentenceListener());
sentenceReader.start();
How can i get inputstream for netty server port being used?
SentenceReader does not have any method to accept "streamed in" data, however with subclassing, it can be made to accept the data.
The core of SentenceReader uses a DataReader for its data, normally this datareader is polled from a seperate thread SentenceReader itself, and we can modify this structure to get what we need.
First, we subclass SentenceReader with our own class, give it the proper constructor and methods we want, and remove the effect of the start and stop methods. We provide null as the file for now (and hope future versions provide a method to pass a datareader in directly)
public class NettySentenceReader extends SentenceReader {
public NettySentenceReader () {
super((InputStream)null);
}
#Override
public void start() {
}
#Override
public void stop() {
}
}
We now need to implement all functionality of the internal class DataReader inside our own Netty handler, to replicate the same behaviour
public class SentenceReaderHandler extends
SimpleChannelInboundHandler<String> {
private SentenceFactory factory;
private SentenceReader parent;
public SentenceReaderHandler (SentenceReader parent) {
this.parent = parent;
}
#Override
public void channelRegistered(ChannelHandlerContext ctx) {
if(!ctx.channel().isActive())
return;
//ActivityMonitor monitor = new ActivityMonitor(parent);
this.factory = SentenceFactory.getInstance();
}
#Override
public void channelActive(ChannelHandlerContext ctx) {
//ActivityMonitor monitor = new ActivityMonitor(parent);
this.factory = SentenceFactory.getInstance();
}
#Override
// This method will be renamed to `messageReceived` in Netty 5.0.0
protected void channelRead0(ChannelHandlerContext ctx, String data)
throws Exception {
if (SentenceValidator.isValid(data)) {
monitor.refresh();
Sentence s = factory.createParser(data);
parent.fireSentenceEvent(s);
} else if (!SentenceValidator.isSentence(data)) {
parent.fireDataEvent(data);
}
}
#Override
public void channelInactive(ChannelHandlerContext ctx) {
//monitor.reset();
parent.fireReadingStopped();
}
#Override
public void channelUnregistered(ChannelHandlerContext ctx) {
if(!ctx.channel().isActive())
return;
//monitor.reset();
parent.fireReadingStopped();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
parent.handleException("Data read failed", e);
}
}
Finally, we need to integrate this into a Netty pipeline:
SentenceReader reader = new NettySentenceReader();
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
private static final StringDecoder DECODER = new StringDecoder();
#Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(DECODER);
pipeline.addLast(new SentenceReaderHandler(reader));
}
});
You can't easily as InputStream is blocking and netty is an async - non blocking API.
I am using Netty v4.1.9final and trying to send a message from client to server. I tried setting up the channel client initializer with the handler as follows on the client side:
final Bootstrap bootstrap = BootstrapGenerator.generate();
bootstrap.handler(new XmlClientInitializer());
XMLClientInitializer
public class XmlClientInitializer extends ChannelInitializer<SocketChannel> {
#Override
public void initChannel(SocketChannel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("fileEncoder", new FileEncoder());
pipeline.addLast("handler", new XmlSenderHandler());
}
}
FileEncoder
public class FileEncoder extends MessageToByteEncoder<String> {
XmlSenderHandler
public class XmlSenderHandler extends ChannelOutboundHandlerAdapter {
private static final Logger log = LogManager.getLogger(XmlSenderHandler.class.getName());
private static ChannelHandlerContext ctx;
#Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
log.info("attempting to write messages to server {}", msg.toString());
ctx.write(msg, promise);
}
#Override
#SuppressWarnings("FutureReturnValueIgnored")
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
}
}
Even though the FileEncoder is defined first in the pipeline, it gets called after the xml handler (which is not what I am seeking). Is this because the FileEncoder is extending MessageToByteEncoder or am I configuring the channel incorrectly?
No, the pipeline is configured correctly. The point is that the inbound event is processed from the first handler to the last, and the outbound event is processed from the last handler to the first one.
ChannelPipeline doc
I am new to Apache Camel and trying to receive a simple SNMP trap.
I have the Maven project set up with camel-core and org.apache.servicemix.bundles.snmp4j.
I have not been able to find any SNMP examples, but based on other examples I have come up with this Main class:
public class Main {
public static Processor myProcessor = new Processor() {
public void process(Exchange arg0) throws Exception {
// save to database
}
};
public static void main(String[] args) {
CamelContext context = new DefaultCamelContext();
context.addComponent("snmp", new SnmpComponent());
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("snmp:127.0.0.1:162?protocol=udp&type=TRAP").process(myProcessor);
}
};
try {
context.addRoutes(builder);
context.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
However when I run it in Eclipse as Java application it just exits after running for half a second. I was expecting it to keep running and listening to 127.0.0.1:162 ...
Any help is greatly appreciated
One way to at least pick up a trap and print to System.out is like so:
public class SNMPTrap {
private Main main;
public static void main(String[] args) throws Exception {
SNMPTrap snmpTrap = new SNMPTrap();
snmpTrap.boot();
}
#SuppressWarnings("deprecation")
public void boot() throws Exception {
main = new Main();
main.bind("snmp", new SnmpComponent());
main.addRouteBuilder(new MyRouteBuilder());
main.addMainListener(new Events());
System.out.println("Starting SNMPTrap. Use ctrl + c to terminate the JVM.\n");
main.run();
}
private static class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("snmp:127.0.0.1:162?protocol=udp&type=TRAP").process(myProcessor)
.bean("snmp");
}
}
public static Processor myProcessor = new Processor() {
public void process(Exchange trap) throws Exception {
System.out.println(trap.getIn().getBody(String.class));
// Save to DB or do other good stuff
}
};
public static class Events extends MainListenerSupport {
#Override
public void afterStart(MainSupport main) {
System.out.println("SNMPTrap is now started!");
}
#Override
public void beforeStop(MainSupport main) {
System.out.println("SNMPTrap is now being stopped!");
}
}
}
However, I get warning that Main which is part of Camel core is deprecated now.
In Netty 3.5 we use SimpleChannelHandler, which provides method for both event types. How do I use the same approach in Netty 4.0.0?
To be more specific i m looking for a substitute of the method below
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
}
I am trying to send message to all clients connected to the server.
Here is the example for netty 3.x
ChannelGroup allConnected = new DefaultChannelGroup("all-connected");
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
super.channelConnected(ctx, e);
allConnected.add(e.getChannel());
}
and then to send messages to all channels connected
ChannelBuffer cb = ChannelBuffers.wrappedBuffer("hello".getBytes(Charset.forName("UTF-8")));
allConnected.write(cb);
This is what i need to do in Netty 4.21 final but i couldn't find a similar method which provided me the needed functionality.
I'm not really sure what you mean by both event types. I guess you mean client and server? I use ChannelInboundHandlerAdapter for that:
public class ServerCommunicationHandler extends ChannelInboundHandlerAdapter {
private final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
channels.add(ctx.channel());
ctx.fireChannelActive();
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
broadcastMessage(msg);
ctx.fireChannelRead(msg);
}
#Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
channels.remove(ctx.channel());
ctx.fireChannelInactive();
}
public void broadcastMessage(Object object) {
channels.writeAndFlush(object);
}
}
In Netty 3 I can handle open/close events with ChannelUpstreamHandler, like
pipeline.addLast("channelGroupHandler", new SimpleChannelUpstreamHandler() {
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
...
}
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
...
}
});
but in Netty 4 it's doesn't work. So, how I can handle this events now?
If you check New and noteworthy in 4.0 you can see that:
In 3.x, When a new connected Channel is created at least three ChannelStateEvents are triggered: channelOpen, channelBound, and channelConnected. When a Channel is closed, at least 3 more: channelDisconnected, channelUnbound, and channelClosed.
In 4.x, channelOpen, channelBound, and channelConnected have been merged to channelActive. Otherwise, channelDisconnected, channelUnbound, and channelClosed have been merged to channelInactive.
You should use the new API and that's it.
Looks like the new class to use in Netty 4 is ChannelInboundHandlerAdapter
pipeline.addLast("channelGroupHandler", new ChannelInboundHandlerAdapter() {
public void channelActive(ChannelHandlerContext ctx) {
...
}
public void channelInactive(ChannelHandlerContext ctx) {
...
}
});