You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Scott Parkerson <Sc...@ateb.com> on 2009/09/09 22:56:29 UTC
How to send a JMS message from a webservice
I have a JAX-RS webservice deployed on Apache CXF inside of Apache
ServiceMix 4 that, upon validating the incoming object, will need to
send the message to a JMS queue (e.g. ActiveMQ). What is the easiest
way to do this from inside of Apache CXF?
I've Googled a bit, and there are a lot of examples for setting up a
webservice that goes *straight* into JMS, but I'm looking to sending
the message after doing some processing. Here's a code snippet:
@POST
@Path("/sendfoo")
public Response sendfoo(sendfooRequest sendfooRequest)
{
logger.debug("[rest] sendfoo called");
logger.debug("[rest] sendfooRequest campaignId " +
sendfooRequest.getCampaignId());
logger.debug("[rest] sendfooRequest fooNumber " +
sendfooRequest.getFooNumber());
logger.debug("[rest] sendfooRequest messageType " +
sendfooRequest.getMessageType());
// TODO: Figure out why this doesn't seem to work the way I'd
expect it to.
// This is probably something weird with jettison's
JSON marshalling that
// I don't understand.
HashMap<String, String> tagHash = sendfooRequest.getTags();
if (tagHash != null)
{
for (String tag : tagHash.keySet())
{
logger.debug("[rest] sendfooREquest tag " + tag + ",
value " + tagHash.get(tag));
}
}
// TODO: validate a sendfooRequest. Perhaps have the request
object validate itself?
//if (!sendfooRequest.isValid())
//{
// return Response.status(400).build();
//}
// TODO: if the sendfooRequest validates, then send it along
to the next endpoint;
// otherwise, return an HTTP error 400 (Bad Request)
and an error response.
// Return HTTP response 202 Accepted
return Response.status(202).build();
}
Basically, I need to know how to send my sendfooRequest object along
to JMS/ActiveMQ.
Thanks!
Scott
Re: How to send a JMS message from a webservice
Posted by Christian Schneider <ch...@die-schneider.net>.
Hi Scott,
I have not yet used the @Produce style myself. Perhaps there is
something special to configure here. I guess you could ask on the Camel
User list why your one Example worked and the other did not.
I guess cxfrs could really be worth a try.
Btw. Is there any reason why you use seda: instead of direct:? I guess
direct endpoints could be more efficient.
Perhaps there is even a way to avoid CXF at all. You could try to use a
jetty http endpoint and parse the request with jaxb.
At least if jaxb unmarshalling is all you need of rest it could work:
<route>
<from uri="jetty:http://myurl"/>
<unmarshal ref="myJaxb"/>
<to uri="activemq:myqueue"/>
</route>
The following page explains jaxb in Camel:
http://camel.apache.org/jaxb.html
Greetings
Christian
Scott Parkerson schrieb:
> On Fri, 2009-09-11 at 15:31 -0400, Scott Parkerson wrote:
>
>
> Ok, now had I tried your actual suggestion using @EndpointInject things
> would have gone more smoothly for me. I changed my code to:
>
> @EndpointInject(uri = "seda:webrequestqueue")
> private ProducerTemplate<Exchange> webRequestProducer;
>
> .
> .
> .
>
> webRequestProducer.sendBody(sendFooRequest);
>
> and all is well.
>
> I guess my only complaint is that this doesn't "hide middleware" as
> suggested in the docs. Then again, perhaps I'll eventually come around
> to binding a cxfrs: URI to my routes. :D
>
> Any further suggestions?
>
> --sgp
>
>
>> I'm beginning to think I've got the wrong approach to this, but humor me
>> and tell me how I can just send the Foo object.
>>
>> --sgp
>>
>>
>
>
Re: How to send a JMS message from a webservice
Posted by Scott Parkerson <Sc...@ateb.com>.
On Fri, 2009-09-11 at 15:31 -0400, Scott Parkerson wrote:
> On Thu, 2009-09-10 at 10:10 +0200, Christian Schneider wrote:
>
> > Ok .. now I understand. You want to send the pojo to ActiveMQ not the
> > xml. In this case you build the service with CXF and can then use
> > Camel to simply send the pojo to ActiveMQ. You can do this by:
> >
> > public class MyJsonServiceImpl implements MyJsonService {
> > @EndpointInject(uri="activemq:myqueue")
> > ProducerTemplate producer;
> >
> > public void doSomething(MyObject o) {
> > producer.sendBody(o);
> > }
> > }
>
> Ok, this is closer to what I want, but not quite there. I'm using the
> example from the pojo-producing page, and sending the result to a seda
> queue which is then picked up by a content-based router. Here's the
> code:
>
> (the interface code)
>
> @InOnly
> public interface WebRequestProducer
> {
> public void sendToWebRouter(Object o);
> }
>
> (the webrouter configuration)
>
> public void configure() throws Exception
> {
>
> getContext().addInterceptStrategy(new Tracer());
>
> from("seda:webrequestqueue")
> .choice()
> .when(body().isInstanceOf(SendSMSRequest.class))
> .to("activemq:queue:send_sms_req")
> .when(body().isInstanceOf(IncomingSMSRequest.class))
> .to("activemq:queue:inc_sms_req")
> .otherwise().throwFault("Blah." +
> body().toString());
> }
>
> (and finally, the CXF method that calls it)
>
> @Produce(uri = "seda:webrequestqueue")
> private WebRequestProducer webRequestProducer;
>
> @POST
> @Path("/sendfoo")
> public Response sendFoo(SendFooRequest sendFooRequest)
> {
>
> // TODO: validation code, etc.
> webRequestProducer.sendToWebRouter(sendFooRequest);
>
> // Return HTTP response 202 Accepted
> return Response.status(202).build();
>
> }
>
>
>
> Problem is, my message that is generated is a BeanInvocation message
> containing the abstract method invocation, not *just* the POJO.
Ok, now had I tried your actual suggestion using @EndpointInject things
would have gone more smoothly for me. I changed my code to:
@EndpointInject(uri = "seda:webrequestqueue")
private ProducerTemplate<Exchange> webRequestProducer;
.
.
.
webRequestProducer.sendBody(sendFooRequest);
and all is well.
I guess my only complaint is that this doesn't "hide middleware" as
suggested in the docs. Then again, perhaps I'll eventually come around
to binding a cxfrs: URI to my routes. :D
Any further suggestions?
--sgp
>
> I'm beginning to think I've got the wrong approach to this, but humor me
> and tell me how I can just send the Foo object.
>
> --sgp
>
Re: How to send a JMS message from a webservice
Posted by Scott Parkerson <Sc...@ateb.com>.
On Thu, 2009-09-10 at 10:10 +0200, Christian Schneider wrote:
> Ok .. now I understand. You want to send the pojo to ActiveMQ not the
> xml. In this case you build the service with CXF and can then use
> Camel to simply send the pojo to ActiveMQ. You can do this by:
>
> public class MyJsonServiceImpl implements MyJsonService {
> @EndpointInject(uri="activemq:myqueue")
> ProducerTemplate producer;
>
> public void doSomething(MyObject o) {
> producer.sendBody(o);
> }
> }
Ok, this is closer to what I want, but not quite there. I'm using the
example from the pojo-producing page, and sending the result to a seda
queue which is then picked up by a content-based router. Here's the
code:
(the interface code)
@InOnly
public interface WebRequestProducer
{
public void sendToWebRouter(Object o);
}
(the webrouter configuration)
public void configure() throws Exception
{
getContext().addInterceptStrategy(new Tracer());
from("seda:webrequestqueue")
.choice()
.when(body().isInstanceOf(SendSMSRequest.class))
.to("activemq:queue:send_sms_req")
.when(body().isInstanceOf(IncomingSMSRequest.class))
.to("activemq:queue:inc_sms_req")
.otherwise().throwFault("Blah." +
body().toString());
}
(and finally, the CXF method that calls it)
@Produce(uri = "seda:webrequestqueue")
private WebRequestProducer webRequestProducer;
@POST
@Path("/sendfoo")
public Response sendFoo(SendFooRequest sendFooRequest)
{
// TODO: validation code, etc.
webRequestProducer.sendToWebRouter(sendFooRequest);
// Return HTTP response 202 Accepted
return Response.status(202).build();
}
Problem is, my message that is generated is a BeanInvocation message
containing the abstract method invocation, not *just* the POJO.
I'm beginning to think I've got the wrong approach to this, but humor me
and tell me how I can just send the Foo object.
--sgp
Re: How to send a JMS message from a webservice
Posted by Christian Schneider <ch...@die-schneider.net>.
Scott Parkerson schrieb:
>
> On Sep 9, 2009, at 5:36 PM, Christian Schneider wrote:
>
>> I think you could take a look at Apache Camel. If you simply want to
>> send the soap message to jms you would set up a camel route like this:
>>
>> from("http://localhost:9000/MyServicePort").to("jms://myQeueName")
>>
>> Between the two you could insert some processing.
>
> In this case, it's more like:
>
> POST /api/sendfooRequest (JSON body) -> CXF (which validates, and
> turns it into a POJO) -> ActiveMQ -> some other bean to process
Ok .. now I understand. You want to send the pojo to ActiveMQ not the
xml. In this case you build the service with CXF and can then use
Camel to simply send the pojo to ActiveMQ. You can do this by:
public class MyJsonServiceImpl implements MyJsonService {
@EndpointInject(uri="activemq:myqueue")
ProducerTemplate producer;
public void doSomething(MyObject o) {
producer.sendBody(o);
}
}
If you do not like to have the queue name in the annotation you can use
a direct endpoint and define the destination in the camel context. I
hope this is what you were searching for.
The full documentation can be found here:
http://camel.apache.org/pojo-producing.html
http://camel.apache.org/activemq.html
http://camel.apache.org/direct.html
Alternatively you can set up a CXF Endpoint in Camel. In this case you
do not need to write the implementation class.
http://camel.apache.org/cxf.html
So your route would look like:
<route>
<from uri="cxf:bean:routerEndpoint" />
<to uri="activemq:myqueue" />
</route>
If you only want to forward the request this is probably easier.
Btw. Camel also supports request reply in a route like this. So your
component that listens to jms can send a reply message back that is then
returned in the body of the http reply.
Greetings
Christian
>
> I'd rather not have Camel manage the actual front-end response; I'd
> rather have Camel process that after it's passed into the next phase.
>
>> If you only need a transparent bridge from http to jms you could take
>> a look at a project I did:
>> http://www.liquid-reality.de:8080/display/liquid/HTTP2JMSBridge
>
> Good idea, but I still want CXF to do the processing before it gets to
> JMS.
>
> --sgp
>
>
Re: How to send a JMS message from a webservice
Posted by Scott Parkerson <Sc...@ateb.com>.
On Sep 9, 2009, at 5:36 PM, Christian Schneider wrote:
> I think you could take a look at Apache Camel. If you simply want to
> send the soap message to jms you would set up a camel route like this:
>
> from("http://localhost:9000/MyServicePort").to("jms://myQeueName")
>
> Between the two you could insert some processing.
In this case, it's more like:
POST /api/sendfooRequest (JSON body) -> CXF (which validates, and
turns it into a POJO) -> ActiveMQ -> some other bean to process
I'd rather not have Camel manage the actual front-end response; I'd
rather have Camel process that after it's passed into the next phase.
> If you only need a transparent bridge from http to jms you could
> take a look at a project I did:
> http://www.liquid-reality.de:8080/display/liquid/HTTP2JMSBridge
Good idea, but I still want CXF to do the processing before it gets to
JMS.
--sgp
Re: How to send a JMS message from a webservice
Posted by Christian Schneider <ch...@die-schneider.net>.
Hi Scott,
I think you could take a look at Apache Camel. If you simply want to
send the soap message to jms you would set up a camel route like this:
from("http://localhost:9000/MyServicePort").to("jms://myQeueName")
Between the two you could insert some processing.
If you only need a transparent bridge from http to jms you could take a
look at a project I did:
http://www.liquid-reality.de:8080/display/liquid/HTTP2JMSBridge
Greetings
Christian
Scott Parkerson schrieb:
> I have a JAX-RS webservice deployed on Apache CXF inside of Apache
> ServiceMix 4 that, upon validating the incoming object, will need to
> send the message to a JMS queue (e.g. ActiveMQ). What is the easiest
> way to do this from inside of Apache CXF?
>
> I've Googled a bit, and there are a lot of examples for setting up a
> webservice that goes *straight* into JMS, but I'm looking to sending
> the message after doing some processing. Here's a code snippet:
>
> @POST
> @Path("/sendfoo")
> public Response sendfoo(sendfooRequest sendfooRequest)
> {
> logger.debug("[rest] sendfoo called");
>
> logger.debug("[rest] sendfooRequest campaignId " +
> sendfooRequest.getCampaignId());
> logger.debug("[rest] sendfooRequest fooNumber " +
> sendfooRequest.getFooNumber());
> logger.debug("[rest] sendfooRequest messageType " +
> sendfooRequest.getMessageType());
>
> // TODO: Figure out why this doesn't seem to work the way I'd
> expect it to.
> // This is probably something weird with jettison's JSON
> marshalling that
> // I don't understand.
> HashMap<String, String> tagHash = sendfooRequest.getTags();
> if (tagHash != null)
> {
> for (String tag : tagHash.keySet())
> {
> logger.debug("[rest] sendfooREquest tag " + tag + ",
> value " + tagHash.get(tag));
> }
> }
>
> // TODO: validate a sendfooRequest. Perhaps have the request
> object validate itself?
> //if (!sendfooRequest.isValid())
> //{
> // return Response.status(400).build();
> //}
>
> // TODO: if the sendfooRequest validates, then send it along
> to the next endpoint;
> // otherwise, return an HTTP error 400 (Bad Request) and
> an error response.
>
> // Return HTTP response 202 Accepted
> return Response.status(202).build();
>
> }
>
>
> Basically, I need to know how to send my sendfooRequest object along
> to JMS/ActiveMQ.
>
>
> Thanks!
> Scott
>