2
votes

We have an spring-boot application deployed in embedded jetty server listening on port X. Now I am integrating Apache Camel in this existing application by defining routes. The goal is to move few rest end points to camel routes that will be proxied to some other service. I am unable to understand following

  • When I use "jetty:http://localhost:Y/myapp" as one of route endpoints. It worked without any error. Does that mean Camel created its own jetty instance ?

  • When I use "jetty:http://localhost:X/myapp" - it again worked without giving error that address X is in use

I would like to keep control of jetty server configuration as they were and let camel listen to already existing rest end points.

2
You mention "existing REST endpoints": I think you might want to consider directly integrating your existing REST endpoints with Camel, without going down to the servlet level. That's pretty easy to do if you use JAX-RS with Apache CXF as the implementation (check out the CXFRS and CXF Bean components), but you can also use a Camel ProducerTemplate in your existing controller to send a message to a Camel route. It might help if you gave more detail about your use case (e.g. do you want to redirect a broad range of URL paths, or only some specific ones?) and about your existing REST endpoints. - Cyäegha
Thanks for your time. Previously our application contacted single backend (say original.com) Now we have extracted some functionality and created micro-service for them. This means original.com/moved-context-path should be redirected to new backend new.com/moved-context-path. We want to deploy using Apache Camel as proxy for selected REST API - DanglingPointer
My understanding is that the same application will contain both some REST services implementations (the ones which haven't been extracted so far) and some redirections to external REST services (the new Camel routes). What do you use to expose the remaining REST services? JAX-RS (if yes, is it CXF?), spring-mvc, Restlet, maybe something else? Also, do you want to blindly redirect any path that looks like original.com/foo/* or only some specific paths like original.com/foo/bar1 and original.com/foo/bar2? - Cyäegha
Note: I ask all this because I suspect your question is an example of the XY problem: you ask about how to use the Jetty component, but maybe the actual solution is to use another Camel component entirely. - Cyäegha
To answer above question - yes, we would like to blindly redirect original.com/foo/bar1 to new.com/foo/bar and rest of the REST endpoints exposed currently using spring RestController with jetty remain the same - DanglingPointer

2 Answers

2
votes

If you can configure a servlet mapping which matches all paths which need to be redirected (for example, paths like foo/* are always redirected), then things are pretty easy. If this doesn't work you, I will try to edit my answer later.

The relevant page from the official docs is here. The interesting example for you is the one using the servlet component, because you already have a servlet container (Jetty) configured and running.

First, need to configure the Camel servlet. It depends on how your existing servlet(s) are configured; for instance, using a web.xml file, add:

<servlet>
  <servlet-name>CamelServlet</servlet-name>
  <servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>CamelServlet</servlet-name>
  <url-pattern>/foo/*</url-pattern>
</servlet-mapping>

Or, if you are using spring-boot, you can just register the following bean:

@Bean
public ServletRegistrationBean servletRegistrationBean() {
    CamelHttpTransportServlet servlet = new CamelHttpTransportServlet("CamelServlet");
    servlet.setServletName();
    return new ServletRegistrationBean(servlet,"/foo/*");
}

Anyway, once you have the Camel servlet registered with your Jetty instance, you can use the servlet component, and redirect everything:

from("servlet:foo?matchOnUriPrefix=true")
.to("http4://new.com/foo?bridgeEndpoint=true&throwExceptionOnFailure=false");
  • http4 is the HTTP4 component, based on Apache HTTPClient 4.x. (you can still use the HTTP component base on HTTPClient 3.x if you want).
  • matchOnUriPrefix=true will match wildcards
  • bridgeEndpoint=true means we are acting as a proxy
  • throwExceptionOnFailure=false means errors returned by the new server will just be relayed to the caller, without being handled by Camel.

A request to http://old.com/foo/some/crazy/path/i/just/made/up should be redirected to http://new.com/foo/some/crazy/path/i/just/made/up (and likely result in a 404 error from the new.com server, which will be simply forwarded to the initial caller).

1
votes

Camel does not listen to "already existing" endpoints in the way you're expecting; it creates its own using the scheme-indicated component. You've created a Jetty endpoint (i.e. "jetty:..."), so Camel spins up a Camel Jetty component to handle HTTP requests at that endpoint.

If you want to use Camel as a proxy to redirect (which might be more easily accomplished with a network load balancer), then you'd spin up Camel routes to replace the existing endpoints and route them to the new endpoints. from("jetty:http://oldendpoint.com") .to("jetty:http://newendpoint.com");