Using Camel in existing Spring Boot application with Jetty Server - java

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.

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).

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");

Related

How does a request reaches Resource class in Jersey RESTful API?

I have been using Jersey, Tomcat, and Dropwizard for quite some time. But I am still not able to get what all actions happen from the point a request reaches port 8080 of a server to the point when it hits one of the methods annotated with #Path.
It will be really helpful if someone can help me with all(or a few important) layers in the whole architecture of restful API. For simplicity assume I have an application built with glassfish-jersey and deployed as the fat war using Tomcat.
When Jersey starts up, it will introspect registered resource classes and build a model of all the resources. This model includes the resource classes, the resources methods, and the paths and content-types that map to those resources/resource methods.
Jersey itself runs as a Servlet inside a Servlet container (e.g. Tomcat, Grizzly). The entry point Servlet is the Jersey ServletContainer. So when a request comes in, if the requested URI matches the configured servlet-mapping, the Servlet container will forward the request to the Jersey Servlet. Based on the requested URI and content negotiation, Jersey will go into the model mapping and determine which resource class and method should be called, and then call that method.

JerseyTest framework: Testing my proxyservlet in integration tests

I have a ProxyServlet (org.mitre.dsmiley.httpproxy) in my code which does some operations and forwards certain url's ending with */xyz to a different application. I have integration tests covering my application( using JerseyTest framework) and want to make the integration-tests pass through the proxy servlet.
Currently my test case deployment configuration is as below:
ServletDeploymentContext.forServlet(new ServletContainer(internalConfigureResourceConfig(resourceConfig))).build()
Now, to test my proxy-servlet, if I change the configuration as below,
ServletDeploymentContext.forServlet(MyProxyServlet.class).build()
I am not able to add the url-pattern servlet-mapping above and the proxy-servlet is being called for all the url's. Can someone tell me how can I add the url-mapping configuration dynamically for the
ServletDeploymentContext.forServlet
I have checked all the methods but unable to do so
I have understood where I went wrong. When I add below statement,
ServletDeploymentContext.forServlet(MyProxyServlet.class).build()
I am adding MyProxyServlet as the only "default" servlet and hence even if I add servletPath() as the url-mapping it did not work as that was the only servlet present. So every request was sent to the servlet even if mapping criteria is not satisfied.
When I add another servlet with servletPath as /* then all other requests went to other servlet and the required requests came to my MyProxyServlet

How Spring boot internally handles the http request here?

I see here spring boot packages the microservice artifact as jar file . It handles the http web request through module spring-boot-starter-web.
My understanding is spring boot internally does is
Makes the web server up
creates the war file , then host the war file on server.
Then http requests are handled through servlet lying under spring-boot-starter-web
Is my understnading correct ?
Your understanding is almost correct:
Starts a embedded tomcat server
Instructs the tomcat server how to act
HTTP requests are handled by an underlaying DispatcherServlet
spring boot entry point is main method, inside the main method we are calling SpringApplication.run(<#SpringBootApplication annotated class name> ,arguments);
when we invoking main method, SpringApplication class internally start the embedded server, configuratation and deploy the application in server...
here dispatcher servlet registered in servlet context on OnCondtion checking basis, if we are added spring-boot-starter-web then it checking condtion dispatcher-servlet available or not inside the class path if available then it will in registers the dispatcher-servlet in servlet context

Configuring servlet url-patterns without web.xml

I know this can be done in servlet 3.0 with the #Webservlet annotation where you just assign the url-patterns and not have to do any configurations within a web.xml. Is there a way to programmatically assign a servlets url-pattern for applications running servlet 2.5?
I am creating a library which multiple applications will depend on and trying to make it so each of these applications do not have to explicitly configure any servlet url mappings for the servlets in the library I am creating within their respective web.xml file.
Thanks,
Since the web.xml and #Webservlet are both mechanisms for the server to know where to route requests by examining the war, you would have to be able to manipulate the server if you wanted to do it in code. This is at least theoretically possible, since the server could offer for example a JMX endpoint for configuration or you could go directly into the innards of the server.
However while it might be possible, it would be a non-standard way and you would have to write different tricks for all the servers you want to support. That's not something you want to do.
Finally, if you're creating a library, why does it have servlets in it? It shouldn't be the responsibility of the library to create servlets or decide which urls they're assigned to.

Jetty WebSockets over HTTPS configured through the WebSocketServlet

I have seen many examples on how to configure Jetty for HTTPS SSL for Jetty but they all seem to utilize a separate Server class containing a main method for execution. I want to execute my WebServlet as a standard servlet configured via the web.xml file. I currently have:
#WebServlet
public class MonitoringServlet extends WebSocketServlet {
#Override
public void configure(WebSocketServletFactory factory) {
factory.register(MonitoringSocket.class);
}
}
Where would I place my SSL Servlet configuration code? In the configure method of this Servlet? In the init method?
I do understand that in this case there is no need for instantiating a Server object and using .start() and .join
Servlets are just a means of producing a response to a request.
Typically a request can be from HTTP/0.9, HTTP/1.0, HTTP/1.1, or HTTP/2.
Using SSL/TLS for the secure part of the protocol.
Technically speaking, HTTP isn't even required for Servlets to function.
The protocol used to submit the request is outside of the control of the Servlet you are implementing to provide a response.
In Jetty, you'll want:
a Server instance
at least 1 Connector configured for SSL/TLS
at least 1 handler assigned to the Server
Using servlets without all of the baggage of a "web application" (a "web application" typically has a WEB-INF/web.xml, WEB-INF/classes, and WEB-INF/lib/*.jar) this would be a ServletContextHandler
Using servlets with a "web application" this would be a WebAppContext
This setup can come from a configured ${jetty.base} in the jetty-distribution or via embedded-jetty use of Java to build up the server, its connectors, and its handlers.

Categories