Eric created CXF-8973:
-------------------------

             Summary: NettyHttpServerEngineFactory shuts down all netty 
instances when SpringContext is shutdown
                 Key: CXF-8973
                 URL: https://issues.apache.org/jira/browse/CXF-8973
             Project: CXF
          Issue Type: Bug
            Reporter: Eric


{color:#000000}NettyHttpServerEngineFactory{color} and 
{color:#000000}{color:#000000}JettyHttpServerEngineFactory are very similar in 
how they manage their ports and their lifecycle. There seems, however, to be 
minor difference in the Netty...Factory which seems to be the potential cause 
of bugs:
{color}{color}
{color:#000000}{color:#000000}{color:#000000}
{color}{color}{color}
{code:java}
class JettyHTTPServerEngineFactory {
 ...

 JettyHTTPServerEngineFactory(Bus bus) {
   setBus(bus);
 }

 void setBus(Bus bus) {
    this.bus = bus;
    if (bus != null) {
        bus.setExtension(this, JettyHTTPServerEngineFactory.class);
        lifeCycleManager = bus.getExtension(BusLifeCycleManager.class);
        if (null != lifeCycleManager) {
            lifeCycleManager.registerLifeCycleListener(new 
JettyBusLifeCycleListener());
        }
    }
  }

  class JettyBusLifeCycleListener implements BusLifeCycleListener { ... }

  ...

{code}
{color:#000000}{color:#000000}vs{color}{color}
 
{code:java}
class NettyHttpServerEngineFactory implements BusLifeCycleListener { 
  NettyHttpServerEngineFactory (Bus bus) {
    setBus(bus);
  }

  void setBus(Bus bus) {
    this.bus = bus;
    if (bus != null) {
        bus.setExtension(this, NettyHttpServerEngineFactory.class);
        lifeCycleManager = bus.getExtension(BusLifeCycleManager.class);
        if (null != lifeCycleManager) {
            lifeCycleManager.registerLifeCycleListener(this);
        }
    }
  }

  ...

{code}
{color:#000000}{color:#000000}Both Variants seem to be very similar, however 
there is a subtle difference when it comes to this class:{color}{color}
 
{code:java}
class CXFBusLifeCycleManager implements BusLifeCycleManager {

  void initComplete() {
    if (bus != null){
      bus.getExtension(ConfiguredBeanLocator.class)
        .getBeansOfType(BusLifeCycleListener.class);
    }
    ...
  } 

  ...
}{code}
{color:#000000}{color:#000000}Because NettyHttpServerEngineFactory implements 
BusLifeCycleListener, it can be found as an Extension in the LifeCycleManager, 
which cause the Constructor with the Bus Parameter to be call, which in turn 
automatically registers the Factory for automatic shutdown when a spring 
context is closed.{color}{color}
 
{color:#000000}{color:#000000}This can have unexpected side-effects, when, for 
example in tests, Spring Contexts are created and destroyed on demand and 
combined with indendenpend server instances, like this:

{color}{color}
{code:java}
class TestWithNetty {

  @BeforeAll
  static void setupServer() {

    JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
    sf.setResourceClasses(SomeWebResource.class);
    sf.setAddress("http://localhost:9000";);

    Server server = sf.create();
  }

  @RepeatedTest(2)
  void runtTestWithSpringContext(@Autowired ApplicationContextRunner runner) {
     runner.run(ctx -> // do something with spring context, calling 
localhost:9000);
  }
}
{code}
{color:#000000}{color:#000000}This scenario, when called with a dependency on 
this works:{color}{color}
{code:java}
org.apache.cxf:cxf-rt-transports-http-jetty {code}
{color:#000000}{color:#000000}That is, since netty is never registered as a 
outside of the beforeblock{color}{color}
 
 
{color:#000000}{color:#000000}The same scenario with netty, however 
fails:{color}{color}
{code:java}
org.apache.cxf:cxf-rt-transports-http-netty-server {code}
{color:#000000}{color:#000000}That is the Case because after the first test, 
the spring context is shutdown, which has the side effekt of destroying all 
netty servers, even those which where never managed by spring at all, simply 
because the constructor NettyHttpServerEngineFactory (Bus bus) was implicitly 
called by .getBeansOfType(BusLifeCycleListener.class), which registered the 
factory in the LifeCycle of the SpringBus{color}{color}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to