Newbie: Netty & Spring
Nicholas Hagen
nicholas.hagen at znetdevelopment.com
Wed Aug 19 22:40:25 EDT 2009
As promised, here are some of my latest examples of how I have been
using Spring using autowiring and annotations within Spring (version
2.5.6).
Step 1:
/META-INF/applicationContext.xml
- this specifies the properties required to enable annotation
processing and auto detection. Change com.xyz in base-package to the
base package (and subpackages) to be searched for annotations.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/
beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- auto discover annotated classes -->
<context:component-scan base-package="com.xyz" />
<!-- support annotated classes and properties -->
<context:annotation-config/>
</beans>
Step 2:
Start application and spring application context
public static void main(String[] args)
throws Exception
{
// load and start spring
ApplicationContext context = new ClassPathXmlApplicationContext
(
new String[] { "/META-INF/applicationContext.xml" }
);
// load server
MyServer server = (MyServer) context.getBean("myServer",
MyServer.class);
server.start();
}
Step 3:
Define server as a spring bean responsible for setting up Netty.
@Component
public class MyServer
{
@Autowired
private MyServerPipelineFactory _pipelineFactory;
private Channel _server;
public MyServer()
{
super();
}
public void start()
{
// configure factory
ChannelFactory factory = new NioServerSocketChannelFactory
(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
);
// configure pipeline factory and bootstrap
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(this._pipelineFactory);
// bootstrap.setOption("child.tcpNoDelay", true);
// bootstrap.setOption("child.keepAlive", true);
// bind and start to accept incoming connections
this._server = bootstrap.bind(new InetSocketAddress(TCP_PORT));
}
Step 4:
Define the custom pipeline factory for creating the relevant handlers.
@Component
public class MyServerPipelineFactory implements ChannelPipelineFactory
{
@Autowired
private MyRequestHandler _handler;
public ChannelPipeline getPipeline() throws Exception
{
// create a default pipeline implementation
ChannelPipeline pipeline = Channels.pipeline();
// setup whatever encoders/decoders you need
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// add processing handler (auto-injected via spring)
pipeline.addLast("handler", this._handler);
// return pipeline
return pipeline;
}
}
Step 5:
Define the processing handler to handle business logic
@Component
@ChannelPipelineCoverage(ChannelPipelineCoverage.ALL)
public class MyRequestHandler extends SimpleChannelUpstreamHandler
{
// inject other spring beans as you need
@Autowired
private OtherSpringBeans _otherSpringBean;
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
ExceptionEvent event)
throws Exception
{
event.getCause().printStackTrace();
event.getChannel().close();
}
@Override
public void messageReceived(ChannelHandlerContext ctx,
MessageEvent event)
throws Exception
{
// handle event and its object (ie: string for string decoder)
// use any autowired beans to perform logic against it
}
}
That is the basic path I follow. Now I can easily add and inject
beans by simply declaring a class, marking it as a spring @Component,
and then adding the @Autowire to the class. I have been doing this
for a few different projects now and it is extremely beneficial. For
example, it allows you to change implementations by creating a
different @Component instance.
The problem with this approach though is that as the handler is
injected into a singleton class, the handler is also a singleton.
Thus, you cannot do a stateful handler that is request specific.
There may be a way to do that within Spring, but I have not
investigated as I have had no need yet. Generally, my business logic
is not stateful, just the decoders (ie: frame decoder) is stateful and
those are manually created in the pipeline.
Other things you can do as well is inject a list of handlers into a
class such as @Autowire List<Handler> _handlers. In that case, Spring
will find every @Component that implements Handler and inject as a
list. Then, just add each of those handlers to the pipeline. Using
this approach, you can add handlers automatically to a pipeline by
merely creating a new class and marking it as a @Component. That
really simplifies and abstracts the pipeline. The problem here is
that there is no order defined for the handlers in the list and the
order generally matters in the pipeline. You could solve that by
providing some annotation and processing that annotaiton while
building the pipeline. Alternatively, you could mark the handlers as
Comparable and then use a sorted list letting the handlers compare
against themselves (maybe using some order constant defined in each
class).
Anyways, if you need further help or understanding, let me know.
Thanks,
=================================
Nicholas Hagen
Software Engineer
www.znetdevelopment.com
=================================
Coming Soon: Push RSS
RSS Viewer (Push) for iPhone OS 3
www.znetdevelopment.com/znet/iphone.html
=================================
On Aug 19, 2009, at 3:18 PM, Nicholas Hagen wrote:
> I have examples I'll forward to the list later tonite.
>
> Nicholas Hagen
> Software Engineer
> www.znetdevelopment.com/blogs
> * sent from my iPhone *
>
> On Aug 19, 2009, at 1:51 PM, Simon James <sjames at btisystems.com>
> wrote:
>
>>
>>
>> Are there any documented examples of how to use Spring to create and
>> bind a
>> pipeline for a simple standalone server, for example like the
>> TimeServer in
>> the user guide?
>>
>> I apologize if this is not the appropriate place for this question.
>> I have
>> searched the forums and other online resources, but failed to find
>> anything
>> specific.
>> --
>> View this message in context: http://n2.nabble.com/Newbie%3A-Netty---Spring-tp3474198p3474198.html
>> Sent from the Netty User Group mailing list archive at Nabble.com.
>> _______________________________________________
>> netty-users mailing list
>> netty-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/netty-users
> _______________________________________________
> netty-users mailing list
> netty-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/netty-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/netty-users/attachments/20090819/f3ffe004/attachment-0001.html
More information about the netty-users
mailing list