Isolating multiple CXFNonSpringServlet

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Isolating multiple CXFNonSpringServlet

Jean-Baptiste Onofré
Hi,

I have extended CXFNonSpringServlet two times:

public class MyServlet1 extends CXFNonSpringServlet {

  @Override
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
    bean.setAddress("/");
    bean.setBus(getBus());
    bean.setProvider(new JacksonJsonProvider());
    bean.setServiceBean(new MyApi());
    bean.create();
  }

}

same with MyServlet2.

MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
Note that I would like to use "/" for JAXRS server address as it's based
directly on the servlet alias (context).

When I start the first servlet (let say MyServlet1), it's OK. However
when I start the second one (let say MyServlet2, but the same happens if
I start MyServlet2 first and MyServlet1), it fails with:

Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
There is an endpoint already running on /.
        at
org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
~[?:?]
        at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
~[?:?]
        at
org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
~[?:?]

So, even if I use two different servlets, it seems CXF has a shared
resource somewhere.

Obviously if I have different address for JAXRS server it works, but
it's not that I want as I'm using two different servlets.

I tried:
- to create a bus dedicated in each servlet
- to create a destination registry in each servlet
but it doesn't help.

So, basically, my question is: is there a way to have completely
isolated CXFNonSpringServlet ?

I gonna dig into CXF code today but if you already have some ideas, it
would be great.

Thanks !
Regards
JB
--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Carlos Sierra Andrés-3
Hi there,

you can have a look at the aries jax-rs whiteboard, we create one
CXFNonSpringServlet per application, and they are all deployed on "/" of
their respective ServletContext.

https://github.com/apache/aries-jax-rs-whiteboard/blob/master/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java

I would say we "only" create a bus per servlet, nothing more, but feel
free to have a look.

I hope this helps.

Carlos.

El 15/10/19 a las 7:44, Jean-Baptiste Onofré escribió:

> Hi,
>
> I have extended CXFNonSpringServlet two times:
>
> public class MyServlet1 extends CXFNonSpringServlet {
>
>    @Override
>    public void init(ServletConfig config) throws ServletException {
>      super.init(config);
>      JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>      bean.setAddress("/");
>      bean.setBus(getBus());
>      bean.setProvider(new JacksonJsonProvider());
>      bean.setServiceBean(new MyApi());
>      bean.create();
>    }
>
> }
>
> same with MyServlet2.
>
> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
> Note that I would like to use "/" for JAXRS server address as it's based
> directly on the servlet alias (context).
>
> When I start the first servlet (let say MyServlet1), it's OK. However
> when I start the second one (let say MyServlet2, but the same happens if
> I start MyServlet2 first and MyServlet1), it fails with:
>
> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
> There is an endpoint already running on /.
>          at
> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
> ~[?:?]
>          at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
> ~[?:?]
>          at
> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
> ~[?:?]
>
> So, even if I use two different servlets, it seems CXF has a shared
> resource somewhere.
>
> Obviously if I have different address for JAXRS server it works, but
> it's not that I want as I'm using two different servlets.
>
> I tried:
> - to create a bus dedicated in each servlet
> - to create a destination registry in each servlet
> but it doesn't help.
>
> So, basically, my question is: is there a way to have completely
> isolated CXFNonSpringServlet ?
>
> I gonna dig into CXF code today but if you already have some ideas, it
> would be great.
>
> Thanks !
> Regards
> JB
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Jean-Baptiste Onofré
Hi Carlos,

thanks, I already create a bus per servlet (it's what I thought it
allows isolation), but doesn't seem to work.

Let me compare with what we do in JAXRS Whiteboard.

Thanks,
Regards
JB

On 15/10/2019 09:24, Carlos Sierra Andrés wrote:

> Hi there,
>
> you can have a look at the aries jax-rs whiteboard, we create one
> CXFNonSpringServlet per application, and they are all deployed on "/" of
> their respective ServletContext.
>
> https://github.com/apache/aries-jax-rs-whiteboard/blob/master/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
>
>
> I would say we "only" create a bus per servlet, nothing more, but feel
> free to have a look.
>
> I hope this helps.
>
> Carlos.
>
> El 15/10/19 a las 7:44, Jean-Baptiste Onofré escribió:
>> Hi,
>>
>> I have extended CXFNonSpringServlet two times:
>>
>> public class MyServlet1 extends CXFNonSpringServlet {
>>
>>    @Override
>>    public void init(ServletConfig config) throws ServletException {
>>      super.init(config);
>>      JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>>      bean.setAddress("/");
>>      bean.setBus(getBus());
>>      bean.setProvider(new JacksonJsonProvider());
>>      bean.setServiceBean(new MyApi());
>>      bean.create();
>>    }
>>
>> }
>>
>> same with MyServlet2.
>>
>> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
>> Note that I would like to use "/" for JAXRS server address as it's based
>> directly on the servlet alias (context).
>>
>> When I start the first servlet (let say MyServlet1), it's OK. However
>> when I start the second one (let say MyServlet2, but the same happens if
>> I start MyServlet2 first and MyServlet1), it fails with:
>>
>> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
>> There is an endpoint already running on /.
>>          at
>> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
>>
>> ~[?:?]
>>          at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
>> ~[?:?]
>>          at
>> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
>>
>> ~[?:?]
>>
>> So, even if I use two different servlets, it seems CXF has a shared
>> resource somewhere.
>>
>> Obviously if I have different address for JAXRS server it works, but
>> it's not that I want as I'm using two different servlets.
>>
>> I tried:
>> - to create a bus dedicated in each servlet
>> - to create a destination registry in each servlet
>> but it doesn't help.
>>
>> So, basically, my question is: is there a way to have completely
>> isolated CXFNonSpringServlet ?
>>
>> I gonna dig into CXF code today but if you already have some ideas, it
>> would be great.
>>
>> Thanks !
>> Regards
>> JB

--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Jean-Baptiste Onofré
In reply to this post by Jean-Baptiste Onofré
Hi,

Thanks Dan, he found a way to fix the issue.

The servlet constructor has been changed to:

    public MyServlet(MyRestApi restApi, DestinationRegistry
destinationRegistry, Bus bus) {
        super(destinationRegistry, false);
        this.restApi = restApi;
        this.setBus(bus);
    }

and the bean registering the servlet has been changed to:

        MyRestApi restApi = new MyRestApi();

        Map<Class<?>, Object> extensions = new HashMap<>();
        DestinationRegistry destinationRegistry = new
DestinationRegistryImpl();
        HTTPTransportFactory httpTransportFactory = new
HTTPTransportFactory(destinationRegistry);
        extensions.put(HTTPTransportFactory.class, httpTransportFactory);
        extensions.put(DestinationRegistry.class, destinationRegistry);
        Bus bus = new ExtensionManagerBus(extensions, null,
getClass().getClassLoader());
        org.apache.cxf.transport.DestinationFactoryManager
destinationFactoryManager =
bus.getExtension(org.apache.cxf.transport.DestinationFactoryManager.class);
        for (String url : HTTPTransportFactory.DEFAULT_NAMESPACES) {
            destinationFactoryManager.registerDestinationFactory(url,
httpTransportFactory);
        }

        MyServlet restServlet = new MyServlet(restApi,
destinationRegistry, bus);


Thanks to that, I'm able to register several servlets each "isolated"
with JAXRS Server.

I think there are couple of bugs in CXF here. For instance, the
setExtension(null, HTTPTransportFactory.class) to remove the default one
should work, but the default is still in there.
I will propose a PR to improve this.

Regards
JB

On 15/10/2019 07:44, Jean-Baptiste Onofré wrote:

> Hi,
>
> I have extended CXFNonSpringServlet two times:
>
> public class MyServlet1 extends CXFNonSpringServlet {
>
>   @Override
>   public void init(ServletConfig config) throws ServletException {
>     super.init(config);
>     JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>     bean.setAddress("/");
>     bean.setBus(getBus());
>     bean.setProvider(new JacksonJsonProvider());
>     bean.setServiceBean(new MyApi());
>     bean.create();
>   }
>
> }
>
> same with MyServlet2.
>
> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
> Note that I would like to use "/" for JAXRS server address as it's based
> directly on the servlet alias (context).
>
> When I start the first servlet (let say MyServlet1), it's OK. However
> when I start the second one (let say MyServlet2, but the same happens if
> I start MyServlet2 first and MyServlet1), it fails with:
>
> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
> There is an endpoint already running on /.
>         at
> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
> ~[?:?]
>         at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
> ~[?:?]
>         at
> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
> ~[?:?]
>
> So, even if I use two different servlets, it seems CXF has a shared
> resource somewhere.
>
> Obviously if I have different address for JAXRS server it works, but
> it's not that I want as I'm using two different servlets.
>
> I tried:
> - to create a bus dedicated in each servlet
> - to create a destination registry in each servlet
> but it doesn't help.
>
> So, basically, my question is: is there a way to have completely
> isolated CXFNonSpringServlet ?
>
> I gonna dig into CXF code today but if you already have some ideas, it
> would be great.
>
> Thanks !
> Regards
> JB
>

--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Jean-Baptiste Onofré
And thanks Carlos for the help as well ;)

Regards
JB

On 15/10/2019 17:04, Jean-Baptiste Onofré wrote:

> Hi,
>
> Thanks Dan, he found a way to fix the issue.
>
> The servlet constructor has been changed to:
>
>     public MyServlet(MyRestApi restApi, DestinationRegistry
> destinationRegistry, Bus bus) {
>         super(destinationRegistry, false);
>         this.restApi = restApi;
>         this.setBus(bus);
>     }
>
> and the bean registering the servlet has been changed to:
>
>         MyRestApi restApi = new MyRestApi();
>
>         Map<Class<?>, Object> extensions = new HashMap<>();
>         DestinationRegistry destinationRegistry = new
> DestinationRegistryImpl();
>         HTTPTransportFactory httpTransportFactory = new
> HTTPTransportFactory(destinationRegistry);
>         extensions.put(HTTPTransportFactory.class, httpTransportFactory);
>         extensions.put(DestinationRegistry.class, destinationRegistry);
>         Bus bus = new ExtensionManagerBus(extensions, null,
> getClass().getClassLoader());
>         org.apache.cxf.transport.DestinationFactoryManager
> destinationFactoryManager =
> bus.getExtension(org.apache.cxf.transport.DestinationFactoryManager.class);
>         for (String url : HTTPTransportFactory.DEFAULT_NAMESPACES) {
>             destinationFactoryManager.registerDestinationFactory(url,
> httpTransportFactory);
>         }
>
>         MyServlet restServlet = new MyServlet(restApi,
> destinationRegistry, bus);
>
>
> Thanks to that, I'm able to register several servlets each "isolated"
> with JAXRS Server.
>
> I think there are couple of bugs in CXF here. For instance, the
> setExtension(null, HTTPTransportFactory.class) to remove the default one
> should work, but the default is still in there.
> I will propose a PR to improve this.
>
> Regards
> JB
>
> On 15/10/2019 07:44, Jean-Baptiste Onofré wrote:
>> Hi,
>>
>> I have extended CXFNonSpringServlet two times:
>>
>> public class MyServlet1 extends CXFNonSpringServlet {
>>
>>   @Override
>>   public void init(ServletConfig config) throws ServletException {
>>     super.init(config);
>>     JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>>     bean.setAddress("/");
>>     bean.setBus(getBus());
>>     bean.setProvider(new JacksonJsonProvider());
>>     bean.setServiceBean(new MyApi());
>>     bean.create();
>>   }
>>
>> }
>>
>> same with MyServlet2.
>>
>> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
>> Note that I would like to use "/" for JAXRS server address as it's based
>> directly on the servlet alias (context).
>>
>> When I start the first servlet (let say MyServlet1), it's OK. However
>> when I start the second one (let say MyServlet2, but the same happens if
>> I start MyServlet2 first and MyServlet1), it fails with:
>>
>> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
>> There is an endpoint already running on /.
>>         at
>> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
>> ~[?:?]
>>         at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
>> ~[?:?]
>>         at
>> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
>> ~[?:?]
>>
>> So, even if I use two different servlets, it seems CXF has a shared
>> resource somewhere.
>>
>> Obviously if I have different address for JAXRS server it works, but
>> it's not that I want as I'm using two different servlets.
>>
>> I tried:
>> - to create a bus dedicated in each servlet
>> - to create a destination registry in each servlet
>> but it doesn't help.
>>
>> So, basically, my question is: is there a way to have completely
>> isolated CXFNonSpringServlet ?
>>
>> I gonna dig into CXF code today but if you already have some ideas, it
>> would be great.
>>
>> Thanks !
>> Regards
>> JB
>>
>

--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Scott Lewis
In reply to this post by Jean-Baptiste Onofré
Howdy,

I'm extending this class:
org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet extends
CXFNonSpringServlet.

I would like to be able to do a similar thing to what was done by JB
with CXFNonSpringServlet but rather by extending CXFNonSpringJaxrsServlet.

Currently, as shown here [1], there is not a constructor for
CXFNonSpringJaxrsServlet that allows the DestinationRegistry and Bus
parameters to be passed into the CXFNonSpringJaxrsServlet. The current
constructors are:

CXFNonSpringJaxrsServlet()

CXFNonSpringJaxrsServlet(Application app)

CXFNonSpringJaxrsServlet(Object singletonService)

CXFNonSpringJaxrsServlet(Set<Object> applicationSingletons)

What I would like to see would be the following:

CXFNonSpringJaxrsServlet(Application app, DestinationRegistry
destinationRegistry, Bus bus)  where the implementation looked like:

     public CXFNonSpringJaxrsServlet(Application app, DestinationRegistry destinationRegistry, Bus bus) {
         super(destinationRegistry, false);
         this.application = app;
         this.setBus(bus);
     }

so that I can do with CXFNonSpringJaxrsServlet what JB does with the
CXFNonSpringServlet superclass.   Or if this is more easily done with
fixes to the superclass...then I could use that as well I expect.

To get such support into future release...would it be best to open a
pull request?   Or is asking here better??

Thanksinadvance,

Scott

[1]
https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java#L95


On 10/15/2019 8:04 AM, Jean-Baptiste Onofré wrote:

> Hi,
>
> Thanks Dan, he found a way to fix the issue.
>
> The servlet constructor has been changed to:
>
>      public MyServlet(MyRestApi restApi, DestinationRegistry
> destinationRegistry, Bus bus) {
>          super(destinationRegistry, false);
>          this.restApi = restApi;
>          this.setBus(bus);
>      }
>
> and the bean registering the servlet has been changed to:
>
>          MyRestApi restApi = new MyRestApi();
>
>          Map<Class<?>, Object> extensions = new HashMap<>();
>          DestinationRegistry destinationRegistry = new
> DestinationRegistryImpl();
>          HTTPTransportFactory httpTransportFactory = new
> HTTPTransportFactory(destinationRegistry);
>          extensions.put(HTTPTransportFactory.class, httpTransportFactory);
>          extensions.put(DestinationRegistry.class, destinationRegistry);
>          Bus bus = new ExtensionManagerBus(extensions, null,
> getClass().getClassLoader());
>          org.apache.cxf.transport.DestinationFactoryManager
> destinationFactoryManager =
> bus.getExtension(org.apache.cxf.transport.DestinationFactoryManager.class);
>          for (String url : HTTPTransportFactory.DEFAULT_NAMESPACES) {
>              destinationFactoryManager.registerDestinationFactory(url,
> httpTransportFactory);
>          }
>
>          MyServlet restServlet = new MyServlet(restApi,
> destinationRegistry, bus);
>
>
> Thanks to that, I'm able to register several servlets each "isolated"
> with JAXRS Server.
>
> I think there are couple of bugs in CXF here. For instance, the
> setExtension(null, HTTPTransportFactory.class) to remove the default one
> should work, but the default is still in there.
> I will propose a PR to improve this.
>
> Regards
> JB
>
> On 15/10/2019 07:44, Jean-Baptiste Onofré wrote:
>> Hi,
>>
>> I have extended CXFNonSpringServlet two times:
>>
>> public class MyServlet1 extends CXFNonSpringServlet {
>>
>>    @Override
>>    public void init(ServletConfig config) throws ServletException {
>>      super.init(config);
>>      JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>>      bean.setAddress("/");
>>      bean.setBus(getBus());
>>      bean.setProvider(new JacksonJsonProvider());
>>      bean.setServiceBean(new MyApi());
>>      bean.create();
>>    }
>>
>> }
>>
>> same with MyServlet2.
>>
>> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
>> Note that I would like to use "/" for JAXRS server address as it's based
>> directly on the servlet alias (context).
>>
>> When I start the first servlet (let say MyServlet1), it's OK. However
>> when I start the second one (let say MyServlet2, but the same happens if
>> I start MyServlet2 first and MyServlet1), it fails with:
>>
>> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
>> There is an endpoint already running on /.
>>          at
>> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
>> ~[?:?]
>>          at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
>> ~[?:?]
>>          at
>> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
>> ~[?:?]
>>
>> So, even if I use two different servlets, it seems CXF has a shared
>> resource somewhere.
>>
>> Obviously if I have different address for JAXRS server it works, but
>> it's not that I want as I'm using two different servlets.
>>
>> I tried:
>> - to create a bus dedicated in each servlet
>> - to create a destination registry in each servlet
>> but it doesn't help.
>>
>> So, basically, my question is: is there a way to have completely
>> isolated CXFNonSpringServlet ?
>>
>> I gonna dig into CXF code today but if you already have some ideas, it
>> would be great.
>>
>> Thanks !
>> Regards
>> JB
>>
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Jean-Baptiste Onofré
Hi,

Do you really ned the JAXRS servlet ?

Starting from CXF NonSpring Servlet, you can mimic the JAXRS servlet.

Anyway, it makes sense to expose a new constructor to simplify the
extension.

Regards
JB

On 05/11/2019 00:46, Scott Lewis wrote:

> Howdy,
>
> I'm extending this class:
> org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet extends
> CXFNonSpringServlet.
>
> I would like to be able to do a similar thing to what was done by JB
> with CXFNonSpringServlet but rather by extending CXFNonSpringJaxrsServlet.
>
> Currently, as shown here [1], there is not a constructor for
> CXFNonSpringJaxrsServlet that allows the DestinationRegistry and Bus
> parameters to be passed into the CXFNonSpringJaxrsServlet. The current
> constructors are:
>
> CXFNonSpringJaxrsServlet()
>
> CXFNonSpringJaxrsServlet(Application app)
>
> CXFNonSpringJaxrsServlet(Object singletonService)
>
> CXFNonSpringJaxrsServlet(Set<Object> applicationSingletons)
>
> What I would like to see would be the following:
>
> CXFNonSpringJaxrsServlet(Application app, DestinationRegistry
> destinationRegistry, Bus bus)  where the implementation looked like:
>
>     public CXFNonSpringJaxrsServlet(Application app, DestinationRegistry
> destinationRegistry, Bus bus) {
>         super(destinationRegistry, false);
>         this.application = app;
>         this.setBus(bus);
>     }
>
> so that I can do with CXFNonSpringJaxrsServlet what JB does with the
> CXFNonSpringServlet superclass.   Or if this is more easily done with
> fixes to the superclass...then I could use that as well I expect.
>
> To get such support into future release...would it be best to open a
> pull request?   Or is asking here better??
>
> Thanksinadvance,
>
> Scott
>
> [1]
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java#L95
>
>
>
> On 10/15/2019 8:04 AM, Jean-Baptiste Onofré wrote:
>> Hi,
>>
>> Thanks Dan, he found a way to fix the issue.
>>
>> The servlet constructor has been changed to:
>>
>>      public MyServlet(MyRestApi restApi, DestinationRegistry
>> destinationRegistry, Bus bus) {
>>          super(destinationRegistry, false);
>>          this.restApi = restApi;
>>          this.setBus(bus);
>>      }
>>
>> and the bean registering the servlet has been changed to:
>>
>>          MyRestApi restApi = new MyRestApi();
>>
>>          Map<Class<?>, Object> extensions = new HashMap<>();
>>          DestinationRegistry destinationRegistry = new
>> DestinationRegistryImpl();
>>          HTTPTransportFactory httpTransportFactory = new
>> HTTPTransportFactory(destinationRegistry);
>>          extensions.put(HTTPTransportFactory.class,
>> httpTransportFactory);
>>          extensions.put(DestinationRegistry.class, destinationRegistry);
>>          Bus bus = new ExtensionManagerBus(extensions, null,
>> getClass().getClassLoader());
>>          org.apache.cxf.transport.DestinationFactoryManager
>> destinationFactoryManager =
>> bus.getExtension(org.apache.cxf.transport.DestinationFactoryManager.class);
>>
>>          for (String url : HTTPTransportFactory.DEFAULT_NAMESPACES) {
>>              destinationFactoryManager.registerDestinationFactory(url,
>> httpTransportFactory);
>>          }
>>
>>          MyServlet restServlet = new MyServlet(restApi,
>> destinationRegistry, bus);
>>
>>
>> Thanks to that, I'm able to register several servlets each "isolated"
>> with JAXRS Server.
>>
>> I think there are couple of bugs in CXF here. For instance, the
>> setExtension(null, HTTPTransportFactory.class) to remove the default one
>> should work, but the default is still in there.
>> I will propose a PR to improve this.
>>
>> Regards
>> JB
>>
>> On 15/10/2019 07:44, Jean-Baptiste Onofré wrote:
>>> Hi,
>>>
>>> I have extended CXFNonSpringServlet two times:
>>>
>>> public class MyServlet1 extends CXFNonSpringServlet {
>>>
>>>    @Override
>>>    public void init(ServletConfig config) throws ServletException {
>>>      super.init(config);
>>>      JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
>>>      bean.setAddress("/");
>>>      bean.setBus(getBus());
>>>      bean.setProvider(new JacksonJsonProvider());
>>>      bean.setServiceBean(new MyApi());
>>>      bean.create();
>>>    }
>>>
>>> }
>>>
>>> same with MyServlet2.
>>>
>>> MyServlet1 has /myservlet1 as alias, MyServlet2 has /myservlet2.
>>> Note that I would like to use "/" for JAXRS server address as it's based
>>> directly on the servlet alias (context).
>>>
>>> When I start the first servlet (let say MyServlet1), it's OK. However
>>> when I start the second one (let say MyServlet2, but the same happens if
>>> I start MyServlet2 first and MyServlet1), it fails with:
>>>
>>> Caused by: org.apache.cxf.service.factory.ServiceConstructionException:
>>> There is an endpoint already running on /.
>>>          at
>>> org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:86)
>>>
>>> ~[?:?]
>>>          at
>>> org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:128)
>>> ~[?:?]
>>>          at
>>> org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:209)
>>>
>>> ~[?:?]
>>>
>>> So, even if I use two different servlets, it seems CXF has a shared
>>> resource somewhere.
>>>
>>> Obviously if I have different address for JAXRS server it works, but
>>> it's not that I want as I'm using two different servlets.
>>>
>>> I tried:
>>> - to create a bus dedicated in each servlet
>>> - to create a destination registry in each servlet
>>> but it doesn't help.
>>>
>>> So, basically, my question is: is there a way to have completely
>>> isolated CXFNonSpringServlet ?
>>>
>>> I gonna dig into CXF code today but if you already have some ideas, it
>>> would be great.
>>>
>>> Thanks !
>>> Regards
>>> JB
>>>

--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Isolating multiple CXFNonSpringServlet

Scott Lewis
Hi JB,

On 11/5/2019 11:24 PM, Jean-Baptiste Onofré wrote:
> Hi,
>
> Do you really ned the JAXRS servlet ?
>
> Starting from CXF NonSpring Servlet, you can mimic the JAXRS servlet.

I know.   In fact I'm already doing that, but it's a pain to have that
extra code in my codebase that I'm not at all familiar with.   It would
be much more convenient for consumers like myself to generalize
CXFNonSpringJaxrsServlet by adding that constructor.

>
> Anyway, it makes sense to expose a new constructor to simplify the
> extension.

Right.  That's what I'm asking for.  Actually if there was some way to
remove/consolidate the Bus and DestinationRegistry code that your
original approach introduced, that would be even better.

Scott