HOW-TO: Jetty, JSON, and Restful Services

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

HOW-TO: Jetty, JSON, and Restful Services

gramanero
I am "very" new to FuseESB and the underlying technology stack, so I apologize up front if I am not using the correct terminology when trying to describe the issues we are running into. We are working on a proof of concept to determine if FuseESB is the direction we want to go for some internal projects. We are very excited about the various capabilities that are readily available and can envision how these pre-built pieces will allow us to build solutions quickly. Having said that, we have having some difficulty in getting a particular route to work and could use some assistance.

There are two problems that we are running in to.

1) Routing XML based messages from a jetty or ActiveMQ endpoint to a .NET restful service without going through a file endpoint.
2) Routing JSON based messages from jetty or ActiveMQ endpoint to a .NET restful svc

The route that we are trying to, ideally, get up and running is as follows:

(client application) --> jetty:http --> ActiveMQ --> .NET Restful Service (JSON)

We are able to send a JSON or XML message to the jetty endpoint; however trying to get the body of the message routed directly to the restul svc has been a bit of a challenge. Even attempting to route the body of the JSON or XML message to a queue, and then to the restful svc is showing similar problems as well. What have been able to get working is the following:

(client application) --> jetty:http --> ActiveMQ --> File --> .NET Restful Service (XML)

We want to get rid of the use of the file system as it slows up the process and is an unnecessary hop. With respect to trying to get the message from jetty to the restul svc or from ActiveMQ to the restful svc, it "feels" like there is data coming out of the "from" endpoint that is negatively colliding with our attempts to forward the message to the restful svc. In the case of jetty:http directly to the restul svc, here is the route:

    <route>
        <from uri="jetty:http://localhost:8888/MetricsEndpoint"/>
        <convertBodyTo type="String" />
        <removeHeader headerName="Host" />
        <removeHeader headerName="Connection" />
        <removeHeader headerName="Accept" />
        <removeHeader headerName="Accept-Language" />
        <removeHeader headerName="Accept-Encoding" />
        <removeHeader headerName="UA-CPU" />
        <removeHeader headerName="User-Agent" />
        <removeHeader headerName="Cache-Control" />
        <removeHeader headerName="Content-Length" />
        <removeHeader headerName="Content-Type" />
        <removeHeader headerName="CamelHttpQuery" />
        <removeHeader headerName="CamelHttpPath" />
        <removeHeader headerName="CamelHttpUri" />
        <removeHeader headerName="CamelHttpUrl" />
        <removeHeader headerName="CamelHttpServletRequest" />
        <removeHeader headerName="CamelHttpServletResponse" />
       
        <to uri="cxfrs:http://localhost:5477/MetricsService/Create/" pattern="InOnly"/>
    </route>

The reason for all of the "removeHeader" elements is that it appears as though the output message from jetty is adding in all of the input message headers, so this is my attempt at clearing them out. I suspect that something similar is happening when routing directly from ActiveMQ to the restful svc. I also suspect that this is why routing through the file system works, because the only information in the file that gets written to disk is the body of the message minus any header information from jetty or ActiveMQ. I attempted to use the Jackson library as a data format for marshalling/unmarshalling, but I'm not quite sure I need it since we are really trying to transform the data between JSON and XML (nor do we really want to). We really want to keep the messages as JSON al the way through the route.

I'm not exactly how much information to provide with post, so I'll give you the current error that we are running into and see where the thread goes from there.

When the restful svc is NOT up and running then I get an error that I would expect:

Caused by: java.net.ConnectException: ConnectException invoking http://localhost:5477/MetricsService/Create/: Connection refused: connect

This tells me (I think) that I am getting to the jetty endpoint and that camel is routing something to the restful svc, but just cannot connect to it.

When I start the restful svc, I get the following:

org.apache.camel.component.cxf.CxfOperationException: JAXRS operation failed invoking http://localhost:8888/MetricsEndpoint with statusCode: 404

I uploaded the service mix log file, so I'm hoping that provided more context.
servicemix.log

ServiceMix Version: 4.4.1-fuse-03-06 (standard out of the box configuration)

One last piece of information is that while we have Java development experience in-house, we are mostly an MS shop. We are trying to get these routes to work with no java development, but rather through the use of Spring.

Any help would be greatly appreciated and obviously if I can provide more information please let me know.

Thanks!




Reply | Threaded
Open this post in threaded view
|

Re: HOW-TO: Jetty, JSON, and Restful Services

Castyn
Just a note, you can remove more than one header at once with

<removeHeaders pattern="Camel*"/> or even <removeHeaders pattern="*"/>

Using wildcards and such.  I don't think the headers that are populated off of the jetty endpoint are going to be causing the issue.   If you are just trying to pass along the JSON string straight through to the CXF producer that is mapped to your webservice you wouldn't need to do any unmarsheling along the way.  

Given that the error returned is a 404, have you used SOAP UI or some other utility to hit the service directly to ensure messages can go through from the box you are running servicemix on?  Seems that a webserver might be listening, but that the path is not correct.  It may be that the operation name in your instance is not recognized as a URL path.
Reply | Threaded
Open this post in threaded view
|

Re: HOW-TO: Jetty, JSON, and Restful Services

gramanero
Thank you for the tip about removeHeaders. I was wondering if there was an easier way to accomplish that. Very much appreciated!

What I noticed when initially trying to route the message from jetty to the restulf svc is that the CamelHttpUrl was incorrect. What was logged in the servicemix.log file was:

http://localhost:5477/MetricsService/Create/MetricsEndpoint/

To me it looks like the jetty endpoint path is being appended to the cxfrs endpoint and then camel is trying to communicate with that, which obviously won't work. That is when I started messing with the headers to try and get them "cleaned up" to what I thought made more sense. Of course, I very well may be doing more harm than good. When I take out the removeHeader elements in the route I get the following error:

Caused by: java.lang.IllegalArgumentException: Illegal character(s) in message header value: HTTP/1.1 200

As far as verifying the restful svc itself, I was able to use the Composer tab in Fiddler to fire off a JSON request and it all worked just fine. I basically threw a breakpoint in the .NET restful svc and verified that the callers data was passed correctly, so based on that it doesn't appear to be a problem with the service itself. I also got it to work via a powershell script. I tried using soapUI (and had success with it in the past), but when the restful svc method gets invoked, the input argument is null. I'm sure I'm doing something stupid in soapUI, but I didn't feel like fighting with the tool so I just ended up using Fiddler.

Currently I am running everything on a local workstation.

Thank you for the response!
Reply | Threaded
Open this post in threaded view
|

Re: HOW-TO: Jetty, JSON, and Restful Services

Willem.Jiang
Administrator
In reply to this post by gramanero
Did you need to do some transformation on the request?
If not you can use the http endpoint to send the request without letting
cxf endpoint do the addition work.


On 5/30/12 12:01 AM, gramanero wrote:

> I am "very" new to FuseESB and the underlying technology stack, so I
> apologize up front if I am not using the correct terminology when trying to
> describe the issues we are running into. We are working on a proof of
> concept to determine if FuseESB is the direction we want to go for some
> internal projects. We are very excited about the various capabilities that
> are readily available and can envision how these pre-built pieces will allow
> us to build solutions quickly. Having said that, we have having some
> difficulty in getting a particular route to work and could use some
> assistance.
>
> There are two problems that we are running in to.
>
> 1) Routing XML based messages from a jetty or ActiveMQ endpoint to a .NET
> restful service without going through a file endpoint.
> 2) Routing JSON based messages from jetty or ActiveMQ endpoint to a .NET
> restful svc
>
> The route that we are trying to, ideally, get up and running is as follows:
>
> (client application) -->  jetty:http -->  ActiveMQ -->  .NET Restful Service
> (JSON)
>
> We are able to send a JSON or XML message to the jetty endpoint; however
> trying to get the body of the message routed directly to the restul svc has
> been a bit of a challenge. Even attempting to route the body of the JSON or
> XML message to a queue, and then to the restful svc is showing similar
> problems as well. What have been able to get working is the following:
>
> (client application) -->  jetty:http -->  ActiveMQ -->  File -->  .NET Restful
> Service (XML)
>
> We want to get rid of the use of the file system as it slows up the process
> and is an unnecessary hop. With respect to trying to get the message from
> jetty to the restul svc or from ActiveMQ to the restful svc, it "feels" like
> there is data coming out of the "from" endpoint that is negatively colliding
> with our attempts to forward the message to the restful svc. In the case of
> jetty:http directly to the restul svc, here is the route:
>
>      <route>
>          <from uri="jetty:http://localhost:8888/MetricsEndpoint"/>
> <convertBodyTo type="String" />
> <removeHeader headerName="Host" />
> <removeHeader headerName="Connection" />
> <removeHeader headerName="Accept" />
> <removeHeader headerName="Accept-Language" />
> <removeHeader headerName="Accept-Encoding" />
> <removeHeader headerName="UA-CPU" />
> <removeHeader headerName="User-Agent" />
> <removeHeader headerName="Cache-Control" />
> <removeHeader headerName="Content-Length" />
> <removeHeader headerName="Content-Type" />
> <removeHeader headerName="CamelHttpQuery" />
> <removeHeader headerName="CamelHttpPath" />
> <removeHeader headerName="CamelHttpUri" />
> <removeHeader headerName="CamelHttpUrl" />
> <removeHeader headerName="CamelHttpServletRequest" />
> <removeHeader headerName="CamelHttpServletResponse" />
>
>          <to uri="cxfrs:http://localhost:5477/MetricsService/Create/"
> pattern="InOnly"/>
>      </route>
>
> The reason for all of the "removeHeader" elements is that it appears as
> though the output message from jetty is adding in all of the input message
> headers, so this is my attempt at clearing them out. I suspect that
> something similar is happening when routing directly from ActiveMQ to the
> restful svc. I also suspect that this is why routing through the file system
> works, because the only information in the file that gets written to disk is
> the body of the message minus any header information from jetty or ActiveMQ.
> I attempted to use the Jackson library as a data format for
> marshalling/unmarshalling, but I'm not quite sure I need it since we are
> really trying to transform the data between JSON and XML (nor do we really
> want to). We really want to keep the messages as JSON al the way through the
> route.
>
> I'm not exactly how much information to provide with post, so I'll give you
> the current error that we are running into and see where the thread goes
> from there.
>
> When the restful svc is NOT up and running then I get an error that I would
> expect:
>
> Caused by: java.net.ConnectException: ConnectException invoking
> http://localhost:5477/MetricsService/Create/: Connection refused: connect
>
> This tells me (I think) that I am getting to the jetty endpoint and that
> camel is routing something to the restful svc, but just cannot connect to
> it.
>
> When I start the restful svc, I get the following:
>
> org.apache.camel.component.cxf.CxfOperationException: JAXRS operation failed
> invoking http://localhost:8888/MetricsEndpoint with statusCode: 404
>
> I uploaded the service mix log file, so I'm hoping that provided more
> context.
> http://camel.465427.n5.nabble.com/file/n5713702/servicemix.log
> servicemix.log
>
> ServiceMix Version: 4.4.1-fuse-03-06 (standard out of the box configuration)
>
> One last piece of information is that while we have Java development
> experience in-house, we are mostly an MS shop. We are trying to get these
> routes to work with no java development, but rather through the use of
> Spring.
>
> Any help would be greatly appreciated and obviously if I can provide more
> information please let me know.
>
> Thanks!
>
>
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/HOW-TO-Jetty-JSON-and-Restful-Services-tp5713702.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>


--
Willem
----------------------------------
CamelOne 2012 Conference, May 15-16, 2012: http://camelone.com
FuseSource
Web: http://www.fusesource.com
Blog:    http://willemjiang.blogspot.com (English)
          http://jnn.javaeye.com (Chinese)
Twitter: willemjiang
Weibo: willemjiang
Reply | Threaded
Open this post in threaded view
|

Re: HOW-TO: Jetty, JSON, and Restful Services

gramanero
Currently there is no need to perform any transforms on the request. Just a straight pass through camel.

Sorry for my ignorance, but what would the route look like if I were to take your suggestion of using the http endpoint to send the request?

Thank you for your response.
Reply | Threaded
Open this post in threaded view
|

Re: HOW-TO: Jetty, JSON, and Restful Services

gramanero
Ok, after toying around with it I realized that I messed up the uri for the cxfrs endpoint. I have it working now. I would still be interested in seeing the route that send the request via the http endpoint, just to educate myself more.

Thank you for all the help. The final route ends up looking like this:

    <route>
        <from uri="jetty:http://localhost:8888/MetricsEndpoint"/>
        <convertBodyTo type="String" />
        <removeHeaders pattern="*" />
        <setHeader headerName="Content-Type"><constant>application/json</constant></setHeader>       
        <to uri="cxfrs:http://localhost:5477/MetricsService/" pattern="InOnly"/>
    </route>