You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Daniel Bimschas <bi...@itm.uni-luebeck.de> on 2013/03/20 20:03:20 UTC

Re: Programmatically adding a Servlet

Hi Martin, all,

after a longer break I got back to this topic and finally managed to achieve most of my goals. However, I'm somehow stuck with what might be a trivial problem if you know what to look for. I publish a JAX-RS service using the CXFNonSpringJaxRsServlet (see [1]) that returns an JAXB annotated Bean when being called with GET. This works fine for XML but not for JSON. So if I run

  curl -v -H "Accept: application/xml" http://localhost:8080/rest/v2.0/

I'll get this as result:

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?><demoDto><name>myName</name></demoDto>

But if I run

  curl -v -H "Accept: application/json" http://localhost:8080/rest/v2.0/

I get

  No message body writer has been found for response class DemoDto.

As you can see in [1] I tried to configure JSONProvider in separate ways. I also tried to create the Servlet completely different, using JAXRSServerFactoryBean method (see https://gist.github.com/danbim/5207449). While this also worked in principle, it also failed to serialize to JSON with the same error message.

Does somebody know what I'm doing wrong?

Cheers,
Daniel

[1] https://github.com/itm/service-publisher/blob/master/cxf/src/main/java/de/uniluebeck/itm/servicepublisher/cxf/ServicePublisherJaxRsService.java#L49

On 07.01.2013, at 16:26, Martin Fernau wrote:

> Hmm, then I have no further idea.
> My program is completely controlled via code. I don't use any kind of
> config file and Endpoint.publish doesn't start a new jetty-instance for me.
> This way I start my jetty-server (8.0.3) and publish my services and
> Apache CXF (2.4.2) to it:
> 
> --- cut
> Server server = new Server();
> ArrayList<Connector> connectors = new ArrayList<Connector>();
> 
> // for each ServerPort your Server should listen to
> SelectChannelConnector connector = new SelectChannelConnector();
> connector.setPort(p);
> connectors.add(connector);
> 
> // telling jetty to listen the following ports
> server.setConnectors(connectors.toArray(new Connector[]{}));
> 
> // Creating the ServletContextHandler
> ServletContextHandler servletContext = new
> 	ServletContextHandler(ServletContextHandler.SESSIONS);
>        servletContext.setContextPath("/");
> 
> ContextHandlerCollection contexts = new ContextHandlerCollection();
> contexts.setHandlers(new Handler[] { servletContext });
> 
> server.setHandler(contexts);
> 
> // Adding my CXFServlet
> ServletHolder sh = new ServletHolder(new CXFServlet(this));
> servletContext.getServletHandler().addServletWithMapping(sh, "/services/*");
> 
> // Adding all further Servlets like the CXF-Servlet above
> 
> // Start Jetty
> server.start();
> --- cut
> 
> AFAIK, if you start jetty, you can't add further servlets during runtime
> in this way. I don't know _when_ you call Endpoint.publish in your code.
> For me this all happens on startup of my system and after I start the
> jetty server with "server.start();" I don't call Endpoint.publish any more.
> 
> Regards
> Martin
> 
> 
> Am 07.01.2013 15:31, schrieb Daniel Bimschas:
>> No, no. I also use javax.xml.ws.Endpoint. But as CXF is extending the javax.xml.ws.spi.Provider class in org.apache.cxf.jaxws.spi.ProviderImpl calling Endpoint.publish() results in a call of org.apache.cxf.jaxws.EndpointImpl.doPublish().
>> 
>> On 07.01.2013, at 15:20, Martin Fernau wrote:
>> 
>>> Hm - for me it's not "org.apache.cxf.jaxws.EndpointImpl". I use
>>> "javax.xml.ws.Endpoint" in my loadBus Method. Maybe this is your problem.
>>> 
>>> HTH
>>> Martin
>>> 
>>> Am 07.01.2013 13:44, schrieb Daniel Bimschas:
>>>> I keep running into the same problem. org.apache.cxf.jaxws.EndpointImpl.doPublish(...) still tries to start a new Jetty instance. Also I can't find any setter or similar functionality to pass an existing instance to EndpointImpl...
>>>> 
>>>> On 07.01.2013, at 13:31, Daniel Bimschas wrote:
>>>> 
>>>>> Forget the question! Got it now that this is just your use/test case having this DefaultHTTPServerEngine ;-) I'll try with the snippet...
>>>>> 
>>>>> On 07.01.2013, at 13:16, Daniel Bimschas wrote:
>>>>> 
>>>>>> Martin,
>>>>>> 
>>>>>> that looks like exactly what I'm looking for! Unfortunately there seems to be no class called DefaultHTTPServerEngine. Is this code snippet up to date with the current release (I'm using 2.7.1)?
>>>>>> 
>>>>>> Cheers,
>>>>>> Daniel
>>>>>> 
>>>>>> On 07.01.2013, at 13:05, Martin Fernau wrote:
>>>>>> 
>>>>>>> Hi Daniel,
>>>>>>> 
>>>>>>> programmatically adding a WS-Endpoint was a bit more tricky. For this to
>>>>>>> work I did the follwoing:
>>>>>>> I write a CXFServlet-Class extending from CXFNonSpringServlet like this:
>>>>>>> 
>>>>>>> --- cut
>>>>>>> public class CXFServlet extends CXFNonSpringServlet {
>>>>>>> 	private Logger logger = Logger.getLogger(CXFServlet.class);
>>>>>>> 	private DefaultHTTPServerEngine httpServerEngine;
>>>>>>> 	
>>>>>>> 	public CXFServlet(DefaultHTTPServerEngine httpServerEngine) {
>>>>>>> 		super();
>>>>>>> 		this.httpServerEngine = httpServerEngine;
>>>>>>> 	}
>>>>>>> 	
>>>>>>> 	@Override
>>>>>>> 	public void loadBus(ServletConfig servletConfig) {
>>>>>>> 		super.loadBus(servletConfig);
>>>>>>> 		logger.info("Loading CXF servlet...");
>>>>>>> 		BusFactory.setDefaultBus(this.getBus());
>>>>>>> 		
>>>>>>> 		Set<String> endpoints = httpServerEngine.getJaxServices().keySet();
>>>>>>> 		for (String endpoint : endpoints) {
>>>>>>> 			Endpoint.publish(endpoint,
>>>>>>> httpServerEngine.getJaxServices().get(endpoint));				
>>>>>>> 		}
>>>>>>> 	}
>>>>>>> }
>>>>>>> --- cut
>>>>>>> 
>>>>>>> This CXFServlet I add like this:
>>>>>>> 
>>>>>>> --- cut
>>>>>>> CXFServlet servlet = new CXFServlet(httpServerEngine), "/services/*";
>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>> 		servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>> --- cut
>>>>>>> 
>>>>>>> The "loadBus" method from my CXFServlet gets called automatically from
>>>>>>> CXF somewhen. Within this method I just use the reference to my
>>>>>>> DefaultHTTPServerEngine Object to obtain a list of my WS-Objects I want
>>>>>>> to add to my system. Theoretically you just add all WS-Objects in this
>>>>>>> method like this:
>>>>>>> 
>>>>>>> --- cut
>>>>>>> Endpoint.publish("myService", objectOfClassImplementingWSInterface);
>>>>>>> --- cut
>>>>>>> 
>>>>>>> You need to know that the endpoint "myService" is relative to the path I
>>>>>>> used to add my CXFServlet in jetty. As I used "/services/*" for this
>>>>>>> path in Jetty, the real path for Endpoint.publish("myService", ...)" is
>>>>>>> "/services/myService".
>>>>>>> 
>>>>>>> HTH
>>>>>>> Martin
>>>>>>> 
>>>>>>> 
>>>>>>> Am 07.01.2013 11:31, schrieb Daniel Bimschas:
>>>>>>>> Hi Martin,
>>>>>>>> 
>>>>>>>> thank you for this answer. I actually already did this myself and it works fine for adding a normal servlet. But when I add an JAX-RS application using JAXRSServerFactoryBean (or a JAX-WS endpoint using Endpoint.publish(...)) it tries to start another Jetty instance on the same port :-(.
>>>>>>>> 
>>>>>>>> It is pretty obvious to me that a "ServerFactory" creates a new Jetty instance. However, I did not find another way yet to programmatically add a JAX-WS/JAX-RS service instance to the root context.
>>>>>>>> 
>>>>>>>> https://gist.github.com/4473947 shows how I construct my server instance.
>>>>>>>> 
>>>>>>>> So, to me it seems that I have to let the CXF framework know of the existence of the Jetty instance. Does somebody have an idea?
>>>>>>>> 
>>>>>>>> Best,
>>>>>>>> Daniel
>>>>>>>> 
>>>>>>>> On 05.01.2013, at 19:02, Martin Fernau wrote:
>>>>>>>> 
>>>>>>>>> Not sure if there is a way to do this with CXF - but I do it with jetty itself:
>>>>>>>>> 
>>>>>>>>> servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
>>>>>>>>> servletContext.setContextPath("/");
>>>>>>>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>>>>>>>> contexts.setHandlers(new Handler[] { securityHandler, servletContext, webAppContext });
>>>>>>>>> // Regiser on server
>>>>>>>>> server.setHandler(contexts);
>>>>>>>>> // For each servlet you want to add do this
>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>> String servletPath = "/some/where";
>>>>>>>>> servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>> 
>>>>>>>>> Regards
>>>>>>>>> Martin
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Am 05.01.2013 17:47, schrieb Daniel Bimschas:
>>>>>>>>>> Hi list,
>>>>>>>>>> 
>>>>>>>>>> Is there a way with CXF to programmatically add a good old HttpServlet instance to an already running instance of the embedded Jetty container?
>>>>>>>>>> 
>>>>>>>>>> This way I would be able to add a WebSocketServlet to Jetty...
>>>>>>>>>> 
>>>>>>>>>> Best regards,
>>>>>>>>>> Daniel
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> -- 
>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>> 
>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>> 
>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>> 
>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>> USt-ID-Nr. DE 178 554 522
>>>>>>>>> 
>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für den Adressaten bestimmt.
>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail aus Ihrem System.
>>>>>>>>> Vielen Dank!
>>>>>>>>> 
>>>>>>>>> This email is only intended for the addressee. The content of this email, including all attachments is confidential and includes privileged material.
>>>>>>>>> If you are not the intended recipient, please do not forward or disclose this email, do not open any attachments or make copies or save this email anywhere. Please inform us about the error by returning this email or by calling us on our phone +49 (0)5651 9599-0. Please then finally delete this email from your system.
>>>>>>>>> Thank you very much.
>>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> -- 
>>>>>>> FERNAUSOFT GmbH
>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>> 
>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>> 
>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>> Internet http://www.fernausoft.de
>>>>>>> 
>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>> Steuernummer 025 233 00041
>>>>>>> USt-ID-Nr. DE 178 554 622
>>>>>>> 
>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>>>> den Adressaten bestimmt.
>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>>>> aus Ihrem System.
>>>>>>> Vielen Dank!
>>>>>>> 
>>>>>>> This email is only intended for the addressee. The content of this
>>>>>>> email, including all attachments is confidential and includes privileged
>>>>>>> material.
>>>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>>>> this email, do not open any attachments or make copies or save this
>>>>>>> email anywhere. Please inform us about the error by returning this email
>>>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>>>> delete this email from your system.
>>>>>>> Thank you very much.
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>>> 
>>> 
>>> -- 
>>> FERNAUSOFT GmbH
>>> Gartenstraße 42 - 37269 Eschwege
>>> 
>>> Telefon (0 56 51) 95 99-0
>>> Telefax (0 56 51) 95 99-90
>>> 
>>> eMail martin.fernau@fernausoft.de
>>> Internet http://www.fernausoft.de
>>> 
>>> Handelsregister Eschwege, HRB 1585
>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>> Steuernummer 025 233 00041
>>> USt-ID-Nr. DE 178 554 622
>>> 
>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>> den Adressaten bestimmt.
>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>> aus Ihrem System.
>>> Vielen Dank!
>>> 
>>> This email is only intended for the addressee. The content of this
>>> email, including all attachments is confidential and includes privileged
>>> material.
>>> If you are not the intended recipient, please do not forward or disclose
>>> this email, do not open any attachments or make copies or save this
>>> email anywhere. Please inform us about the error by returning this email
>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>> delete this email from your system.
>>> Thank you very much.
>>> 
>>> 
>> 
> 


Re: Programmatically adding a Servlet

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 21/03/13 18:10, Daniel Bimschas wrote:
> Whooohoo! That exactly did the trick! Thank you so much for saving me even more unproductive hours of guessing!
Thanks for the update; note you can also register Jackson if needed instead
Cheers, Sergey
>
> Cheers,
> Daniel
>
> On 20.03.2013, at 23:24, Sergey Beryozkin wrote:
>
>> Hi
>> On 20/03/13 19:03, Daniel Bimschas wrote:
>>> Hi Martin, all,
>>>
>>> after a longer break I got back to this topic and finally managed to achieve most of my goals. However, I'm somehow stuck with what might be a trivial problem if you know what to look for. I publish a JAX-RS service using the CXFNonSpringJaxRsServlet (see [1]) that returns an JAXB annotated Bean when being called with GET. This works fine for XML but not for JSON. So if I run
>>>
>>>    curl -v -H "Accept: application/xml" http://localhost:8080/rest/v2.0/
>>>
>>> I'll get this as result:
>>>
>>>    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><demoDto><name>myName</name></demoDto>
>>>
>>> But if I run
>>>
>>>    curl -v -H "Accept: application/json" http://localhost:8080/rest/v2.0/
>>>
>>> I get
>>>
>>>    No message body writer has been found for response class DemoDto.
>>>
>>> As you can see in [1] I tried to configure JSONProvider in separate ways. I also tried to create the Servlet completely different, using JAXRSServerFactoryBean method (see https://gist.github.com/danbim/5207449). While this also worked in principle, it also failed to serialize to JSON with the same error message.
>>>
>>> Does somebody know what I'm doing wrong?
>>>
>> Looks like you also need to add Jettison dependency explicitly, at the moment rt-rs-extension-providers has few optional providers bundled and thus the expectation is that the individual optional provider modules will be added explicitly. I was a bit conscious at a time of having 5+ extra very small modules added instead...
>>
>> Give it a try please
>> Cheers, Sergey
>>
>>> Cheers,
>>> Daniel
>>>
>>> [1] https://github.com/itm/service-publisher/blob/master/cxf/src/main/java/de/uniluebeck/itm/servicepublisher/cxf/ServicePublisherJaxRsService.java#L49
>>>
>>> On 07.01.2013, at 16:26, Martin Fernau wrote:
>>>
>>>> Hmm, then I have no further idea.
>>>> My program is completely controlled via code. I don't use any kind of
>>>> config file and Endpoint.publish doesn't start a new jetty-instance for me.
>>>> This way I start my jetty-server (8.0.3) and publish my services and
>>>> Apache CXF (2.4.2) to it:
>>>>
>>>> --- cut
>>>> Server server = new Server();
>>>> ArrayList<Connector>   connectors = new ArrayList<Connector>();
>>>>
>>>> // for each ServerPort your Server should listen to
>>>> SelectChannelConnector connector = new SelectChannelConnector();
>>>> connector.setPort(p);
>>>> connectors.add(connector);
>>>>
>>>> // telling jetty to listen the following ports
>>>> server.setConnectors(connectors.toArray(new Connector[]{}));
>>>>
>>>> // Creating the ServletContextHandler
>>>> ServletContextHandler servletContext = new
>>>> 	ServletContextHandler(ServletContextHandler.SESSIONS);
>>>>         servletContext.setContextPath("/");
>>>>
>>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>>> contexts.setHandlers(new Handler[] { servletContext });
>>>>
>>>> server.setHandler(contexts);
>>>>
>>>> // Adding my CXFServlet
>>>> ServletHolder sh = new ServletHolder(new CXFServlet(this));
>>>> servletContext.getServletHandler().addServletWithMapping(sh, "/services/*");
>>>>
>>>> // Adding all further Servlets like the CXF-Servlet above
>>>>
>>>> // Start Jetty
>>>> server.start();
>>>> --- cut
>>>>
>>>> AFAIK, if you start jetty, you can't add further servlets during runtime
>>>> in this way. I don't know _when_ you call Endpoint.publish in your code.
>>>> For me this all happens on startup of my system and after I start the
>>>> jetty server with "server.start();" I don't call Endpoint.publish any more.
>>>>
>>>> Regards
>>>> Martin
>>>>
>>>>
>>>> Am 07.01.2013 15:31, schrieb Daniel Bimschas:
>>>>> No, no. I also use javax.xml.ws.Endpoint. But as CXF is extending the javax.xml.ws.spi.Provider class in org.apache.cxf.jaxws.spi.ProviderImpl calling Endpoint.publish() results in a call of org.apache.cxf.jaxws.EndpointImpl.doPublish().
>>>>>
>>>>> On 07.01.2013, at 15:20, Martin Fernau wrote:
>>>>>
>>>>>> Hm - for me it's not "org.apache.cxf.jaxws.EndpointImpl". I use
>>>>>> "javax.xml.ws.Endpoint" in my loadBus Method. Maybe this is your problem.
>>>>>>
>>>>>> HTH
>>>>>> Martin
>>>>>>
>>>>>> Am 07.01.2013 13:44, schrieb Daniel Bimschas:
>>>>>>> I keep running into the same problem. org.apache.cxf.jaxws.EndpointImpl.doPublish(...) still tries to start a new Jetty instance. Also I can't find any setter or similar functionality to pass an existing instance to EndpointImpl...
>>>>>>>
>>>>>>> On 07.01.2013, at 13:31, Daniel Bimschas wrote:
>>>>>>>
>>>>>>>> Forget the question! Got it now that this is just your use/test case having this DefaultHTTPServerEngine ;-) I'll try with the snippet...
>>>>>>>>
>>>>>>>> On 07.01.2013, at 13:16, Daniel Bimschas wrote:
>>>>>>>>
>>>>>>>>> Martin,
>>>>>>>>>
>>>>>>>>> that looks like exactly what I'm looking for! Unfortunately there seems to be no class called DefaultHTTPServerEngine. Is this code snippet up to date with the current release (I'm using 2.7.1)?
>>>>>>>>>
>>>>>>>>> Cheers,
>>>>>>>>> Daniel
>>>>>>>>>
>>>>>>>>> On 07.01.2013, at 13:05, Martin Fernau wrote:
>>>>>>>>>
>>>>>>>>>> Hi Daniel,
>>>>>>>>>>
>>>>>>>>>> programmatically adding a WS-Endpoint was a bit more tricky. For this to
>>>>>>>>>> work I did the follwoing:
>>>>>>>>>> I write a CXFServlet-Class extending from CXFNonSpringServlet like this:
>>>>>>>>>>
>>>>>>>>>> --- cut
>>>>>>>>>> public class CXFServlet extends CXFNonSpringServlet {
>>>>>>>>>> 	private Logger logger = Logger.getLogger(CXFServlet.class);
>>>>>>>>>> 	private DefaultHTTPServerEngine httpServerEngine;
>>>>>>>>>> 	
>>>>>>>>>> 	public CXFServlet(DefaultHTTPServerEngine httpServerEngine) {
>>>>>>>>>> 		super();
>>>>>>>>>> 		this.httpServerEngine = httpServerEngine;
>>>>>>>>>> 	}
>>>>>>>>>> 	
>>>>>>>>>> 	@Override
>>>>>>>>>> 	public void loadBus(ServletConfig servletConfig) {
>>>>>>>>>> 		super.loadBus(servletConfig);
>>>>>>>>>> 		logger.info("Loading CXF servlet...");
>>>>>>>>>> 		BusFactory.setDefaultBus(this.getBus());
>>>>>>>>>> 		
>>>>>>>>>> 		Set<String>   endpoints = httpServerEngine.getJaxServices().keySet();
>>>>>>>>>> 		for (String endpoint : endpoints) {
>>>>>>>>>> 			Endpoint.publish(endpoint,
>>>>>>>>>> httpServerEngine.getJaxServices().get(endpoint));				
>>>>>>>>>> 		}
>>>>>>>>>> 	}
>>>>>>>>>> }
>>>>>>>>>> --- cut
>>>>>>>>>>
>>>>>>>>>> This CXFServlet I add like this:
>>>>>>>>>>
>>>>>>>>>> --- cut
>>>>>>>>>> CXFServlet servlet = new CXFServlet(httpServerEngine), "/services/*";
>>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>>> 		servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>>> --- cut
>>>>>>>>>>
>>>>>>>>>> The "loadBus" method from my CXFServlet gets called automatically from
>>>>>>>>>> CXF somewhen. Within this method I just use the reference to my
>>>>>>>>>> DefaultHTTPServerEngine Object to obtain a list of my WS-Objects I want
>>>>>>>>>> to add to my system. Theoretically you just add all WS-Objects in this
>>>>>>>>>> method like this:
>>>>>>>>>>
>>>>>>>>>> --- cut
>>>>>>>>>> Endpoint.publish("myService", objectOfClassImplementingWSInterface);
>>>>>>>>>> --- cut
>>>>>>>>>>
>>>>>>>>>> You need to know that the endpoint "myService" is relative to the path I
>>>>>>>>>> used to add my CXFServlet in jetty. As I used "/services/*" for this
>>>>>>>>>> path in Jetty, the real path for Endpoint.publish("myService", ...)" is
>>>>>>>>>> "/services/myService".
>>>>>>>>>>
>>>>>>>>>> HTH
>>>>>>>>>> Martin
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Am 07.01.2013 11:31, schrieb Daniel Bimschas:
>>>>>>>>>>> Hi Martin,
>>>>>>>>>>>
>>>>>>>>>>> thank you for this answer. I actually already did this myself and it works fine for adding a normal servlet. But when I add an JAX-RS application using JAXRSServerFactoryBean (or a JAX-WS endpoint using Endpoint.publish(...)) it tries to start another Jetty instance on the same port :-(.
>>>>>>>>>>>
>>>>>>>>>>> It is pretty obvious to me that a "ServerFactory" creates a new Jetty instance. However, I did not find another way yet to programmatically add a JAX-WS/JAX-RS service instance to the root context.
>>>>>>>>>>>
>>>>>>>>>>> https://gist.github.com/4473947 shows how I construct my server instance.
>>>>>>>>>>>
>>>>>>>>>>> So, to me it seems that I have to let the CXF framework know of the existence of the Jetty instance. Does somebody have an idea?
>>>>>>>>>>>
>>>>>>>>>>> Best,
>>>>>>>>>>> Daniel
>>>>>>>>>>>
>>>>>>>>>>> On 05.01.2013, at 19:02, Martin Fernau wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Not sure if there is a way to do this with CXF - but I do it with jetty itself:
>>>>>>>>>>>>
>>>>>>>>>>>> servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
>>>>>>>>>>>> servletContext.setContextPath("/");
>>>>>>>>>>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>>>>>>>>>>> contexts.setHandlers(new Handler[] { securityHandler, servletContext, webAppContext });
>>>>>>>>>>>> // Regiser on server
>>>>>>>>>>>> server.setHandler(contexts);
>>>>>>>>>>>> // For each servlet you want to add do this
>>>>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>>>>> String servletPath = "/some/where";
>>>>>>>>>>>> servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>>>>>
>>>>>>>>>>>> Regards
>>>>>>>>>>>> Martin
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Am 05.01.2013 17:47, schrieb Daniel Bimschas:
>>>>>>>>>>>>> Hi list,
>>>>>>>>>>>>>
>>>>>>>>>>>>> Is there a way with CXF to programmatically add a good old HttpServlet instance to an already running instance of the embedded Jetty container?
>>>>>>>>>>>>>
>>>>>>>>>>>>> This way I would be able to add a WebSocketServlet to Jetty...
>>>>>>>>>>>>>
>>>>>>>>>>>>> Best regards,
>>>>>>>>>>>>> Daniel
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>>>>>
>>>>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>>>>>
>>>>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>>>>>
>>>>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>>>>> USt-ID-Nr. DE 178 554 522
>>>>>>>>>>>>
>>>>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für den Adressaten bestimmt.
>>>>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail aus Ihrem System.
>>>>>>>>>>>> Vielen Dank!
>>>>>>>>>>>>
>>>>>>>>>>>> This email is only intended for the addressee. The content of this email, including all attachments is confidential and includes privileged material.
>>>>>>>>>>>> If you are not the intended recipient, please do not forward or disclose this email, do not open any attachments or make copies or save this email anywhere. Please inform us about the error by returning this email or by calling us on our phone +49 (0)5651 9599-0. Please then finally delete this email from your system.
>>>>>>>>>>>> Thank you very much.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>>>
>>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>>>
>>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>>>
>>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>>> USt-ID-Nr. DE 178 554 622
>>>>>>>>>>
>>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>>>>>>> den Adressaten bestimmt.
>>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>>>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>>>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>>>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>>>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>>>>>>> aus Ihrem System.
>>>>>>>>>> Vielen Dank!
>>>>>>>>>>
>>>>>>>>>> This email is only intended for the addressee. The content of this
>>>>>>>>>> email, including all attachments is confidential and includes privileged
>>>>>>>>>> material.
>>>>>>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>>>>>>> this email, do not open any attachments or make copies or save this
>>>>>>>>>> email anywhere. Please inform us about the error by returning this email
>>>>>>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>>>>>>> delete this email from your system.
>>>>>>>>>> Thank you very much.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> FERNAUSOFT GmbH
>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>
>>>>>> Telefon (0 56 51) 95 99-0
>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>
>>>>>> eMail martin.fernau@fernausoft.de
>>>>>> Internet http://www.fernausoft.de
>>>>>>
>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>> Steuernummer 025 233 00041
>>>>>> USt-ID-Nr. DE 178 554 622
>>>>>>
>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>>> den Adressaten bestimmt.
>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>>> aus Ihrem System.
>>>>>> Vielen Dank!
>>>>>>
>>>>>> This email is only intended for the addressee. The content of this
>>>>>> email, including all attachments is confidential and includes privileged
>>>>>> material.
>>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>>> this email, do not open any attachments or make copies or save this
>>>>>> email anywhere. Please inform us about the error by returning this email
>>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>>> delete this email from your system.
>>>>>> Thank you very much.
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Programmatically adding a Servlet

Posted by Daniel Bimschas <bi...@itm.uni-luebeck.de>.
Whooohoo! That exactly did the trick! Thank you so much for saving me even more unproductive hours of guessing!

Cheers,
Daniel

On 20.03.2013, at 23:24, Sergey Beryozkin wrote:

> Hi
> On 20/03/13 19:03, Daniel Bimschas wrote:
>> Hi Martin, all,
>> 
>> after a longer break I got back to this topic and finally managed to achieve most of my goals. However, I'm somehow stuck with what might be a trivial problem if you know what to look for. I publish a JAX-RS service using the CXFNonSpringJaxRsServlet (see [1]) that returns an JAXB annotated Bean when being called with GET. This works fine for XML but not for JSON. So if I run
>> 
>>   curl -v -H "Accept: application/xml" http://localhost:8080/rest/v2.0/
>> 
>> I'll get this as result:
>> 
>>   <?xml version="1.0" encoding="UTF-8" standalone="yes"?><demoDto><name>myName</name></demoDto>
>> 
>> But if I run
>> 
>>   curl -v -H "Accept: application/json" http://localhost:8080/rest/v2.0/
>> 
>> I get
>> 
>>   No message body writer has been found for response class DemoDto.
>> 
>> As you can see in [1] I tried to configure JSONProvider in separate ways. I also tried to create the Servlet completely different, using JAXRSServerFactoryBean method (see https://gist.github.com/danbim/5207449). While this also worked in principle, it also failed to serialize to JSON with the same error message.
>> 
>> Does somebody know what I'm doing wrong?
>> 
> Looks like you also need to add Jettison dependency explicitly, at the moment rt-rs-extension-providers has few optional providers bundled and thus the expectation is that the individual optional provider modules will be added explicitly. I was a bit conscious at a time of having 5+ extra very small modules added instead...
> 
> Give it a try please
> Cheers, Sergey
> 
>> Cheers,
>> Daniel
>> 
>> [1] https://github.com/itm/service-publisher/blob/master/cxf/src/main/java/de/uniluebeck/itm/servicepublisher/cxf/ServicePublisherJaxRsService.java#L49
>> 
>> On 07.01.2013, at 16:26, Martin Fernau wrote:
>> 
>>> Hmm, then I have no further idea.
>>> My program is completely controlled via code. I don't use any kind of
>>> config file and Endpoint.publish doesn't start a new jetty-instance for me.
>>> This way I start my jetty-server (8.0.3) and publish my services and
>>> Apache CXF (2.4.2) to it:
>>> 
>>> --- cut
>>> Server server = new Server();
>>> ArrayList<Connector>  connectors = new ArrayList<Connector>();
>>> 
>>> // for each ServerPort your Server should listen to
>>> SelectChannelConnector connector = new SelectChannelConnector();
>>> connector.setPort(p);
>>> connectors.add(connector);
>>> 
>>> // telling jetty to listen the following ports
>>> server.setConnectors(connectors.toArray(new Connector[]{}));
>>> 
>>> // Creating the ServletContextHandler
>>> ServletContextHandler servletContext = new
>>> 	ServletContextHandler(ServletContextHandler.SESSIONS);
>>>        servletContext.setContextPath("/");
>>> 
>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>> contexts.setHandlers(new Handler[] { servletContext });
>>> 
>>> server.setHandler(contexts);
>>> 
>>> // Adding my CXFServlet
>>> ServletHolder sh = new ServletHolder(new CXFServlet(this));
>>> servletContext.getServletHandler().addServletWithMapping(sh, "/services/*");
>>> 
>>> // Adding all further Servlets like the CXF-Servlet above
>>> 
>>> // Start Jetty
>>> server.start();
>>> --- cut
>>> 
>>> AFAIK, if you start jetty, you can't add further servlets during runtime
>>> in this way. I don't know _when_ you call Endpoint.publish in your code.
>>> For me this all happens on startup of my system and after I start the
>>> jetty server with "server.start();" I don't call Endpoint.publish any more.
>>> 
>>> Regards
>>> Martin
>>> 
>>> 
>>> Am 07.01.2013 15:31, schrieb Daniel Bimschas:
>>>> No, no. I also use javax.xml.ws.Endpoint. But as CXF is extending the javax.xml.ws.spi.Provider class in org.apache.cxf.jaxws.spi.ProviderImpl calling Endpoint.publish() results in a call of org.apache.cxf.jaxws.EndpointImpl.doPublish().
>>>> 
>>>> On 07.01.2013, at 15:20, Martin Fernau wrote:
>>>> 
>>>>> Hm - for me it's not "org.apache.cxf.jaxws.EndpointImpl". I use
>>>>> "javax.xml.ws.Endpoint" in my loadBus Method. Maybe this is your problem.
>>>>> 
>>>>> HTH
>>>>> Martin
>>>>> 
>>>>> Am 07.01.2013 13:44, schrieb Daniel Bimschas:
>>>>>> I keep running into the same problem. org.apache.cxf.jaxws.EndpointImpl.doPublish(...) still tries to start a new Jetty instance. Also I can't find any setter or similar functionality to pass an existing instance to EndpointImpl...
>>>>>> 
>>>>>> On 07.01.2013, at 13:31, Daniel Bimschas wrote:
>>>>>> 
>>>>>>> Forget the question! Got it now that this is just your use/test case having this DefaultHTTPServerEngine ;-) I'll try with the snippet...
>>>>>>> 
>>>>>>> On 07.01.2013, at 13:16, Daniel Bimschas wrote:
>>>>>>> 
>>>>>>>> Martin,
>>>>>>>> 
>>>>>>>> that looks like exactly what I'm looking for! Unfortunately there seems to be no class called DefaultHTTPServerEngine. Is this code snippet up to date with the current release (I'm using 2.7.1)?
>>>>>>>> 
>>>>>>>> Cheers,
>>>>>>>> Daniel
>>>>>>>> 
>>>>>>>> On 07.01.2013, at 13:05, Martin Fernau wrote:
>>>>>>>> 
>>>>>>>>> Hi Daniel,
>>>>>>>>> 
>>>>>>>>> programmatically adding a WS-Endpoint was a bit more tricky. For this to
>>>>>>>>> work I did the follwoing:
>>>>>>>>> I write a CXFServlet-Class extending from CXFNonSpringServlet like this:
>>>>>>>>> 
>>>>>>>>> --- cut
>>>>>>>>> public class CXFServlet extends CXFNonSpringServlet {
>>>>>>>>> 	private Logger logger = Logger.getLogger(CXFServlet.class);
>>>>>>>>> 	private DefaultHTTPServerEngine httpServerEngine;
>>>>>>>>> 	
>>>>>>>>> 	public CXFServlet(DefaultHTTPServerEngine httpServerEngine) {
>>>>>>>>> 		super();
>>>>>>>>> 		this.httpServerEngine = httpServerEngine;
>>>>>>>>> 	}
>>>>>>>>> 	
>>>>>>>>> 	@Override
>>>>>>>>> 	public void loadBus(ServletConfig servletConfig) {
>>>>>>>>> 		super.loadBus(servletConfig);
>>>>>>>>> 		logger.info("Loading CXF servlet...");
>>>>>>>>> 		BusFactory.setDefaultBus(this.getBus());
>>>>>>>>> 		
>>>>>>>>> 		Set<String>  endpoints = httpServerEngine.getJaxServices().keySet();
>>>>>>>>> 		for (String endpoint : endpoints) {
>>>>>>>>> 			Endpoint.publish(endpoint,
>>>>>>>>> httpServerEngine.getJaxServices().get(endpoint));				
>>>>>>>>> 		}
>>>>>>>>> 	}
>>>>>>>>> }
>>>>>>>>> --- cut
>>>>>>>>> 
>>>>>>>>> This CXFServlet I add like this:
>>>>>>>>> 
>>>>>>>>> --- cut
>>>>>>>>> CXFServlet servlet = new CXFServlet(httpServerEngine), "/services/*";
>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>> 		servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>> --- cut
>>>>>>>>> 
>>>>>>>>> The "loadBus" method from my CXFServlet gets called automatically from
>>>>>>>>> CXF somewhen. Within this method I just use the reference to my
>>>>>>>>> DefaultHTTPServerEngine Object to obtain a list of my WS-Objects I want
>>>>>>>>> to add to my system. Theoretically you just add all WS-Objects in this
>>>>>>>>> method like this:
>>>>>>>>> 
>>>>>>>>> --- cut
>>>>>>>>> Endpoint.publish("myService", objectOfClassImplementingWSInterface);
>>>>>>>>> --- cut
>>>>>>>>> 
>>>>>>>>> You need to know that the endpoint "myService" is relative to the path I
>>>>>>>>> used to add my CXFServlet in jetty. As I used "/services/*" for this
>>>>>>>>> path in Jetty, the real path for Endpoint.publish("myService", ...)" is
>>>>>>>>> "/services/myService".
>>>>>>>>> 
>>>>>>>>> HTH
>>>>>>>>> Martin
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Am 07.01.2013 11:31, schrieb Daniel Bimschas:
>>>>>>>>>> Hi Martin,
>>>>>>>>>> 
>>>>>>>>>> thank you for this answer. I actually already did this myself and it works fine for adding a normal servlet. But when I add an JAX-RS application using JAXRSServerFactoryBean (or a JAX-WS endpoint using Endpoint.publish(...)) it tries to start another Jetty instance on the same port :-(.
>>>>>>>>>> 
>>>>>>>>>> It is pretty obvious to me that a "ServerFactory" creates a new Jetty instance. However, I did not find another way yet to programmatically add a JAX-WS/JAX-RS service instance to the root context.
>>>>>>>>>> 
>>>>>>>>>> https://gist.github.com/4473947 shows how I construct my server instance.
>>>>>>>>>> 
>>>>>>>>>> So, to me it seems that I have to let the CXF framework know of the existence of the Jetty instance. Does somebody have an idea?
>>>>>>>>>> 
>>>>>>>>>> Best,
>>>>>>>>>> Daniel
>>>>>>>>>> 
>>>>>>>>>> On 05.01.2013, at 19:02, Martin Fernau wrote:
>>>>>>>>>> 
>>>>>>>>>>> Not sure if there is a way to do this with CXF - but I do it with jetty itself:
>>>>>>>>>>> 
>>>>>>>>>>> servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
>>>>>>>>>>> servletContext.setContextPath("/");
>>>>>>>>>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>>>>>>>>>> contexts.setHandlers(new Handler[] { securityHandler, servletContext, webAppContext });
>>>>>>>>>>> // Regiser on server
>>>>>>>>>>> server.setHandler(contexts);
>>>>>>>>>>> // For each servlet you want to add do this
>>>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>>>> String servletPath = "/some/where";
>>>>>>>>>>> servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>>>> 
>>>>>>>>>>> Regards
>>>>>>>>>>> Martin
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> Am 05.01.2013 17:47, schrieb Daniel Bimschas:
>>>>>>>>>>>> Hi list,
>>>>>>>>>>>> 
>>>>>>>>>>>> Is there a way with CXF to programmatically add a good old HttpServlet instance to an already running instance of the embedded Jetty container?
>>>>>>>>>>>> 
>>>>>>>>>>>> This way I would be able to add a WebSocketServlet to Jetty...
>>>>>>>>>>>> 
>>>>>>>>>>>> Best regards,
>>>>>>>>>>>> Daniel
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> --
>>>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>>>> 
>>>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>>>> 
>>>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>>>> 
>>>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>>>> USt-ID-Nr. DE 178 554 522
>>>>>>>>>>> 
>>>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für den Adressaten bestimmt.
>>>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail aus Ihrem System.
>>>>>>>>>>> Vielen Dank!
>>>>>>>>>>> 
>>>>>>>>>>> This email is only intended for the addressee. The content of this email, including all attachments is confidential and includes privileged material.
>>>>>>>>>>> If you are not the intended recipient, please do not forward or disclose this email, do not open any attachments or make copies or save this email anywhere. Please inform us about the error by returning this email or by calling us on our phone +49 (0)5651 9599-0. Please then finally delete this email from your system.
>>>>>>>>>>> Thank you very much.
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> --
>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>> 
>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>> 
>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>> 
>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>> USt-ID-Nr. DE 178 554 622
>>>>>>>>> 
>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>>>>>> den Adressaten bestimmt.
>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>>>>>> aus Ihrem System.
>>>>>>>>> Vielen Dank!
>>>>>>>>> 
>>>>>>>>> This email is only intended for the addressee. The content of this
>>>>>>>>> email, including all attachments is confidential and includes privileged
>>>>>>>>> material.
>>>>>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>>>>>> this email, do not open any attachments or make copies or save this
>>>>>>>>> email anywhere. Please inform us about the error by returning this email
>>>>>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>>>>>> delete this email from your system.
>>>>>>>>> Thank you very much.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>>>> 
>>>>> --
>>>>> FERNAUSOFT GmbH
>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>> 
>>>>> Telefon (0 56 51) 95 99-0
>>>>> Telefax (0 56 51) 95 99-90
>>>>> 
>>>>> eMail martin.fernau@fernausoft.de
>>>>> Internet http://www.fernausoft.de
>>>>> 
>>>>> Handelsregister Eschwege, HRB 1585
>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>> Steuernummer 025 233 00041
>>>>> USt-ID-Nr. DE 178 554 622
>>>>> 
>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>> den Adressaten bestimmt.
>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>> aus Ihrem System.
>>>>> Vielen Dank!
>>>>> 
>>>>> This email is only intended for the addressee. The content of this
>>>>> email, including all attachments is confidential and includes privileged
>>>>> material.
>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>> this email, do not open any attachments or make copies or save this
>>>>> email anywhere. Please inform us about the error by returning this email
>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>> delete this email from your system.
>>>>> Thank you very much.
>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 
> 


Re: Programmatically adding a Servlet

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 20/03/13 19:03, Daniel Bimschas wrote:
> Hi Martin, all,
>
> after a longer break I got back to this topic and finally managed to achieve most of my goals. However, I'm somehow stuck with what might be a trivial problem if you know what to look for. I publish a JAX-RS service using the CXFNonSpringJaxRsServlet (see [1]) that returns an JAXB annotated Bean when being called with GET. This works fine for XML but not for JSON. So if I run
>
>    curl -v -H "Accept: application/xml" http://localhost:8080/rest/v2.0/
>
> I'll get this as result:
>
>    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><demoDto><name>myName</name></demoDto>
>
> But if I run
>
>    curl -v -H "Accept: application/json" http://localhost:8080/rest/v2.0/
>
> I get
>
>    No message body writer has been found for response class DemoDto.
>
> As you can see in [1] I tried to configure JSONProvider in separate ways. I also tried to create the Servlet completely different, using JAXRSServerFactoryBean method (see https://gist.github.com/danbim/5207449). While this also worked in principle, it also failed to serialize to JSON with the same error message.
>
> Does somebody know what I'm doing wrong?
>
Looks like you also need to add Jettison dependency explicitly, at the 
moment rt-rs-extension-providers has few optional providers bundled and 
thus the expectation is that the individual optional provider modules 
will be added explicitly. I was a bit conscious at a time of having 5+ 
extra very small modules added instead...

Give it a try please
Cheers, Sergey

> Cheers,
> Daniel
>
> [1] https://github.com/itm/service-publisher/blob/master/cxf/src/main/java/de/uniluebeck/itm/servicepublisher/cxf/ServicePublisherJaxRsService.java#L49
>
> On 07.01.2013, at 16:26, Martin Fernau wrote:
>
>> Hmm, then I have no further idea.
>> My program is completely controlled via code. I don't use any kind of
>> config file and Endpoint.publish doesn't start a new jetty-instance for me.
>> This way I start my jetty-server (8.0.3) and publish my services and
>> Apache CXF (2.4.2) to it:
>>
>> --- cut
>> Server server = new Server();
>> ArrayList<Connector>  connectors = new ArrayList<Connector>();
>>
>> // for each ServerPort your Server should listen to
>> SelectChannelConnector connector = new SelectChannelConnector();
>> connector.setPort(p);
>> connectors.add(connector);
>>
>> // telling jetty to listen the following ports
>> server.setConnectors(connectors.toArray(new Connector[]{}));
>>
>> // Creating the ServletContextHandler
>> ServletContextHandler servletContext = new
>> 	ServletContextHandler(ServletContextHandler.SESSIONS);
>>         servletContext.setContextPath("/");
>>
>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>> contexts.setHandlers(new Handler[] { servletContext });
>>
>> server.setHandler(contexts);
>>
>> // Adding my CXFServlet
>> ServletHolder sh = new ServletHolder(new CXFServlet(this));
>> servletContext.getServletHandler().addServletWithMapping(sh, "/services/*");
>>
>> // Adding all further Servlets like the CXF-Servlet above
>>
>> // Start Jetty
>> server.start();
>> --- cut
>>
>> AFAIK, if you start jetty, you can't add further servlets during runtime
>> in this way. I don't know _when_ you call Endpoint.publish in your code.
>> For me this all happens on startup of my system and after I start the
>> jetty server with "server.start();" I don't call Endpoint.publish any more.
>>
>> Regards
>> Martin
>>
>>
>> Am 07.01.2013 15:31, schrieb Daniel Bimschas:
>>> No, no. I also use javax.xml.ws.Endpoint. But as CXF is extending the javax.xml.ws.spi.Provider class in org.apache.cxf.jaxws.spi.ProviderImpl calling Endpoint.publish() results in a call of org.apache.cxf.jaxws.EndpointImpl.doPublish().
>>>
>>> On 07.01.2013, at 15:20, Martin Fernau wrote:
>>>
>>>> Hm - for me it's not "org.apache.cxf.jaxws.EndpointImpl". I use
>>>> "javax.xml.ws.Endpoint" in my loadBus Method. Maybe this is your problem.
>>>>
>>>> HTH
>>>> Martin
>>>>
>>>> Am 07.01.2013 13:44, schrieb Daniel Bimschas:
>>>>> I keep running into the same problem. org.apache.cxf.jaxws.EndpointImpl.doPublish(...) still tries to start a new Jetty instance. Also I can't find any setter or similar functionality to pass an existing instance to EndpointImpl...
>>>>>
>>>>> On 07.01.2013, at 13:31, Daniel Bimschas wrote:
>>>>>
>>>>>> Forget the question! Got it now that this is just your use/test case having this DefaultHTTPServerEngine ;-) I'll try with the snippet...
>>>>>>
>>>>>> On 07.01.2013, at 13:16, Daniel Bimschas wrote:
>>>>>>
>>>>>>> Martin,
>>>>>>>
>>>>>>> that looks like exactly what I'm looking for! Unfortunately there seems to be no class called DefaultHTTPServerEngine. Is this code snippet up to date with the current release (I'm using 2.7.1)?
>>>>>>>
>>>>>>> Cheers,
>>>>>>> Daniel
>>>>>>>
>>>>>>> On 07.01.2013, at 13:05, Martin Fernau wrote:
>>>>>>>
>>>>>>>> Hi Daniel,
>>>>>>>>
>>>>>>>> programmatically adding a WS-Endpoint was a bit more tricky. For this to
>>>>>>>> work I did the follwoing:
>>>>>>>> I write a CXFServlet-Class extending from CXFNonSpringServlet like this:
>>>>>>>>
>>>>>>>> --- cut
>>>>>>>> public class CXFServlet extends CXFNonSpringServlet {
>>>>>>>> 	private Logger logger = Logger.getLogger(CXFServlet.class);
>>>>>>>> 	private DefaultHTTPServerEngine httpServerEngine;
>>>>>>>> 	
>>>>>>>> 	public CXFServlet(DefaultHTTPServerEngine httpServerEngine) {
>>>>>>>> 		super();
>>>>>>>> 		this.httpServerEngine = httpServerEngine;
>>>>>>>> 	}
>>>>>>>> 	
>>>>>>>> 	@Override
>>>>>>>> 	public void loadBus(ServletConfig servletConfig) {
>>>>>>>> 		super.loadBus(servletConfig);
>>>>>>>> 		logger.info("Loading CXF servlet...");
>>>>>>>> 		BusFactory.setDefaultBus(this.getBus());
>>>>>>>> 		
>>>>>>>> 		Set<String>  endpoints = httpServerEngine.getJaxServices().keySet();
>>>>>>>> 		for (String endpoint : endpoints) {
>>>>>>>> 			Endpoint.publish(endpoint,
>>>>>>>> httpServerEngine.getJaxServices().get(endpoint));				
>>>>>>>> 		}
>>>>>>>> 	}
>>>>>>>> }
>>>>>>>> --- cut
>>>>>>>>
>>>>>>>> This CXFServlet I add like this:
>>>>>>>>
>>>>>>>> --- cut
>>>>>>>> CXFServlet servlet = new CXFServlet(httpServerEngine), "/services/*";
>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>> 		servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>> --- cut
>>>>>>>>
>>>>>>>> The "loadBus" method from my CXFServlet gets called automatically from
>>>>>>>> CXF somewhen. Within this method I just use the reference to my
>>>>>>>> DefaultHTTPServerEngine Object to obtain a list of my WS-Objects I want
>>>>>>>> to add to my system. Theoretically you just add all WS-Objects in this
>>>>>>>> method like this:
>>>>>>>>
>>>>>>>> --- cut
>>>>>>>> Endpoint.publish("myService", objectOfClassImplementingWSInterface);
>>>>>>>> --- cut
>>>>>>>>
>>>>>>>> You need to know that the endpoint "myService" is relative to the path I
>>>>>>>> used to add my CXFServlet in jetty. As I used "/services/*" for this
>>>>>>>> path in Jetty, the real path for Endpoint.publish("myService", ...)" is
>>>>>>>> "/services/myService".
>>>>>>>>
>>>>>>>> HTH
>>>>>>>> Martin
>>>>>>>>
>>>>>>>>
>>>>>>>> Am 07.01.2013 11:31, schrieb Daniel Bimschas:
>>>>>>>>> Hi Martin,
>>>>>>>>>
>>>>>>>>> thank you for this answer. I actually already did this myself and it works fine for adding a normal servlet. But when I add an JAX-RS application using JAXRSServerFactoryBean (or a JAX-WS endpoint using Endpoint.publish(...)) it tries to start another Jetty instance on the same port :-(.
>>>>>>>>>
>>>>>>>>> It is pretty obvious to me that a "ServerFactory" creates a new Jetty instance. However, I did not find another way yet to programmatically add a JAX-WS/JAX-RS service instance to the root context.
>>>>>>>>>
>>>>>>>>> https://gist.github.com/4473947 shows how I construct my server instance.
>>>>>>>>>
>>>>>>>>> So, to me it seems that I have to let the CXF framework know of the existence of the Jetty instance. Does somebody have an idea?
>>>>>>>>>
>>>>>>>>> Best,
>>>>>>>>> Daniel
>>>>>>>>>
>>>>>>>>> On 05.01.2013, at 19:02, Martin Fernau wrote:
>>>>>>>>>
>>>>>>>>>> Not sure if there is a way to do this with CXF - but I do it with jetty itself:
>>>>>>>>>>
>>>>>>>>>> servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
>>>>>>>>>> servletContext.setContextPath("/");
>>>>>>>>>> ContextHandlerCollection contexts = new ContextHandlerCollection();
>>>>>>>>>> contexts.setHandlers(new Handler[] { securityHandler, servletContext, webAppContext });
>>>>>>>>>> // Regiser on server
>>>>>>>>>> server.setHandler(contexts);
>>>>>>>>>> // For each servlet you want to add do this
>>>>>>>>>> ServletHolder sh = new ServletHolder(servlet);
>>>>>>>>>> String servletPath = "/some/where";
>>>>>>>>>> servletContext.getServletHandler().addServletWithMapping(sh, servletPath);
>>>>>>>>>>
>>>>>>>>>> Regards
>>>>>>>>>> Martin
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Am 05.01.2013 17:47, schrieb Daniel Bimschas:
>>>>>>>>>>> Hi list,
>>>>>>>>>>>
>>>>>>>>>>> Is there a way with CXF to programmatically add a good old HttpServlet instance to an already running instance of the embedded Jetty container?
>>>>>>>>>>>
>>>>>>>>>>> This way I would be able to add a WebSocketServlet to Jetty...
>>>>>>>>>>>
>>>>>>>>>>> Best regards,
>>>>>>>>>>> Daniel
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> FERNAUSOFT GmbH
>>>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>>>
>>>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>>>
>>>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>>>
>>>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>>>> Steuernummer 025 233 00041
>>>>>>>>>> USt-ID-Nr. DE 178 554 522
>>>>>>>>>>
>>>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für den Adressaten bestimmt.
>>>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail aus Ihrem System.
>>>>>>>>>> Vielen Dank!
>>>>>>>>>>
>>>>>>>>>> This email is only intended for the addressee. The content of this email, including all attachments is confidential and includes privileged material.
>>>>>>>>>> If you are not the intended recipient, please do not forward or disclose this email, do not open any attachments or make copies or save this email anywhere. Please inform us about the error by returning this email or by calling us on our phone +49 (0)5651 9599-0. Please then finally delete this email from your system.
>>>>>>>>>> Thank you very much.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> FERNAUSOFT GmbH
>>>>>>>> Gartenstraße 42 - 37269 Eschwege
>>>>>>>>
>>>>>>>> Telefon (0 56 51) 95 99-0
>>>>>>>> Telefax (0 56 51) 95 99-90
>>>>>>>>
>>>>>>>> eMail martin.fernau@fernausoft.de
>>>>>>>> Internet http://www.fernausoft.de
>>>>>>>>
>>>>>>>> Handelsregister Eschwege, HRB 1585
>>>>>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>>>>>> Steuernummer 025 233 00041
>>>>>>>> USt-ID-Nr. DE 178 554 622
>>>>>>>>
>>>>>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>>>>>> den Adressaten bestimmt.
>>>>>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>>>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>>>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>>>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>>>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>>>>>> aus Ihrem System.
>>>>>>>> Vielen Dank!
>>>>>>>>
>>>>>>>> This email is only intended for the addressee. The content of this
>>>>>>>> email, including all attachments is confidential and includes privileged
>>>>>>>> material.
>>>>>>>> If you are not the intended recipient, please do not forward or disclose
>>>>>>>> this email, do not open any attachments or make copies or save this
>>>>>>>> email anywhere. Please inform us about the error by returning this email
>>>>>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>>>>>> delete this email from your system.
>>>>>>>> Thank you very much.
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> FERNAUSOFT GmbH
>>>> Gartenstraße 42 - 37269 Eschwege
>>>>
>>>> Telefon (0 56 51) 95 99-0
>>>> Telefax (0 56 51) 95 99-90
>>>>
>>>> eMail martin.fernau@fernausoft.de
>>>> Internet http://www.fernausoft.de
>>>>
>>>> Handelsregister Eschwege, HRB 1585
>>>> Geschäftsführer: Axel Fernau, Ulrich Fernau, Martin Fernau
>>>> Steuernummer 025 233 00041
>>>> USt-ID-Nr. DE 178 554 622
>>>>
>>>> Diese E-Mail und alle beigefügten Dateien sind vertraulich und nur für
>>>> den Adressaten bestimmt.
>>>> Wenn Sie nicht der richtige Adressat sind, leiten Sie diese E-Mail bitte
>>>> nicht weiter, öffnen Sie etwaige Anhänge nicht, machen Sie keine Kopien
>>>> und speichern Sie diese E-Mail nicht. Informieren Sie uns bitte, indem
>>>> Sie uns eine Antwort-Mail senden oder uns telefonisch unter +49 (0)5651
>>>> 9599-0 verständigen. Löschen Sie bitte anschließend die erhaltene E-Mail
>>>> aus Ihrem System.
>>>> Vielen Dank!
>>>>
>>>> This email is only intended for the addressee. The content of this
>>>> email, including all attachments is confidential and includes privileged
>>>> material.
>>>> If you are not the intended recipient, please do not forward or disclose
>>>> this email, do not open any attachments or make copies or save this
>>>> email anywhere. Please inform us about the error by returning this email
>>>> or by calling us on our phone +49 (0)5651 9599-0. Please then finally
>>>> delete this email from your system.
>>>> Thank you very much.
>>>>
>>>>
>>>
>>
>