0

I'm trying to setup a simple UDP server using Netty following the example here but using Spring for wiring dependencies.

My Spring config class:

@Configuration
@ComponentScan("com.example.netty")
public class SpringConfig {

    @Value("${netty.nThreads}")
    private int nThreads;

    @Autowired
    private MyHandlerA myHandlerA;

    @Autowired
    private MyHandlerB myHandlerB;

    @Bean(name = "bootstrap")
    public Bootstrap bootstrap() {
        Bootstrap b = new Bootstrap();
        b.group(group())
                .channel(NioDatagramChannel.class)
                .handler(new ChannelInitializer<DatagramChannel>() {
                    @Override
                    protected void initChannel(DatagramChannel ch) throws Exception {
                        ch.pipeline().addLast(myHandlerA, myHandlerB);
                    }
                });
        return b;
    }

    @Bean(name = "group", destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup group() {
        return new NioEventLoopGroup(nThreads);
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

My server class:

@Component
public class MyUDPServer {

    @Autowired
    private Bootstrap bootstrap;

    @Value("${host}")
    private String host;

    @Value("${port}")
    private int port;

    @PostConstruct
    public void start() throws Exception {
        bootstrap.bind(host, port).sync().channel().closeFuture().await();
        /* Never reached since the main thread blocks due to the call to await() */
    }
}

During the blocking call to await(), I don't see my application listening on the specified interface. I've tried to run the sample (setting up the server directly from the main function) and it works. I didn't find examples for setting up a UDP server using Netty and Spring.

Thanks, Mickael


EDIT:

In order to avoid blocking the Main thread (which is used for Spring configuration), I've created a new thread as follows:

@Component
public class MyUDPServer extends Thread {

    @Autowired
    private Bootstrap bootstrap;

    @Value("${host}")
    private String host;

    @Value("${port}")
    private int port;

    public MyUDPServer() {
        setName("UDP Server");
    }

    @PostConstruct
    @Override
    public synchronized void start() {
        super.start();
    }

    @Override
    public void run() {
        try {
            bootstrap.bind(host, port).sync().channel().closeFuture().await();
        } catch (InterruptedException e) {

        } finally {
            bootstrap.group().shutdownGracefully();
        }
    }

    @PreDestroy
    @Override
    public void interrupt() {
        super.interrupt();
    }
}

I can see the new thread is blocked waiting for Channel close (as in the example). The Main thread can continue Spring configuration. However, it still doesn't work.

manash
  • 6,985
  • 12
  • 65
  • 125

1 Answers1

0

There is no need to wait for termination of the channel in @PostConstruct. Try to remove await().

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • Please see my edit. Note that it works when I run the example. It's like something is preventing the bind. – manash May 28 '14 at 14:49
  • Following my edit, I've tried to create the bootstrap directly in the MyUDPServer constructor and it works now. I still don't understand why. – manash May 28 '14 at 14:57