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

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.

Related

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.

Using Camel in existing Spring Boot application with Jetty Server

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

Changing servlet location on Init()

Is it possible to change the init parameters so that the servlet is created at a different path? I need to create a servlet at a certain path. Furthermore, would it be possible to artificially pass the path inside the init parameters?
As already shown in other answers, the servlet mapping is not controlled by the servlet, therefore you can't change that from within a servlet instance.
However, you can work around this by introducing a level of indirection (something like a "dispatcher" servlet): map your servlet to a wildcard pattern (like /app/*) and inside your servlet decide the actual action based on the request url path: /app/X will trigger some X action, while /app/Y will trigger Y.
Lots of web frameworks will provide the full functionality out of the box: you can have a look at Spring MVC's DispatcherServlet and its HandlerMapping concept, for instance.
Servlets aren't created at a certain path. They are Java objects that the servlet container Java application creates. If you are running Tomcat, for example, your application will run from the /webapps directory. The most you can do is change the Tomcat configuration to run it from some other path, but you'll have to do this before actually starting the application.
Short answer - you can't change anything related to servlet path mapping in init, since servlet container has already read mapping from web.xml.
Longer answer - you may want to look at servlet loader in Tomcat for example, perhaps it's possible to either invoke it's methods through JMX or do something else.
If you just want to have several mappings and choose which one to serve depending on configuration - use Servlet Filter

Java webapps security constraints & custom security providers

I'm creating a restful web service using Resteasy. One thing I need to do is to secure the service using a standard HTTP auth request. The tricky part is that the service is multi-tenant and needs to use one of the path parameters to determine the security realm.
There are a lot of articles typical of this link which describe setting up a single-tenant service. What I can't find is what to configure, and what interfaces to implement to describe my own security which is based on a path parameter + the username in the HTTP authentication method.
I envision that prior to calling any of the application logic, tomcat/resteasy would call a SecurityProvider (or whatever) interface with the HttpServletRequest and have me either throw a 401 or return a SecurityContext that gets passed to the JAX-RS handlers. In that routine, I would inspect the path parameters, and make a determination based on parameter+username+password given in the Basic/Digest/Form.
Is there any such beast?
I thought I'd update this since there's bee little activity on this question.
It looks like there's no baked in feature to do what I envisioned, so instead I extended the RestEasy servlet and added the security checks in my override before passing control back to the stock RestEasy servlet.
Seems to work well.

In Restlet, what's the difference between a Restlet class and a Resource class?

I've gone through the firstResource bit of the Restlet 1.1 tutorial and put together a web service that handles GET, POST, DELETE, PUT by subclassing the Resource class and overriding the appropriate methods and using a Router to attach the subclassed Resource classes.
So I'm left thinking - what's the point of a Restlet?
I can attach a Resource or a Restlet
to an Application Router
A Resource has methods to handle HTTP
GET POST etc.
A Restlet has a handle method - do I somehow forward that on to a Resource class?
What's the difference? When do I use one or the other? What would I put in a Restlet handle method?
Thanks.
Restlet is the base class for various restlet server facilities, among them Application and Router. When its handle() method is called it's supposed to interpret the request, dispatch it to a suitable child restlet or query the matching resource (the GET/POST/... handle methods), and put the result back in the response.
So, restlets and resources are nodes of a tree. Resources are the leafs of that tree.
Restlets usually don't answer to request but delegate them down the tree. Resources actually reply.
In general, you will program only custom resources and use pre-defined restlets.

Categories