Quoting Java Servlet API Spec : "A client (e.g., a Web browser) accesses a Web server and makes an HTTP request.This request is received by the Web server and handed off to the servlet container."
Can anyone elaborate on how exactly this control is passed( from Web server to Servlet Container)?Does it use HTTP connectors of some kind like Apache Coyote?
The implementation detail depends on server-to-server. Http Connector architecture is what used by Apache Tomcat internally.
Web server is nothing but a Java application which opens socket on a port and keeps listening on that port over HTTP protocol + Some other facilities. These some other facilities consist of things like components lifecycle management etc.
Basic task of a web server is to listen for requests on a port number over http protocol and then respond to that. So in most common server available today they keep polling on port 80 over http protocol. When you send some http request on port 80 to the host where the program is listening then program listening responds to that. Now on receiving the request the server program (which is listening on port 80 here) will get a new thread from its thread pool and in that thread will call a servlet's service method (a servlet instance will be created if its the first request see here for more details).
ADDITION:
Web Server is a machine that has a HTTPD service running. When you send the request to server the server intercepts that.Web server is responsible for receiving request and generating response. Now the server gets the input stream on the socket where it was listening. From here it delegates the input to servlet container by wrapping it in a new thread (so that things get processed asynchronously and web server can process other http requests when the previous request is served in a separate thread by servlet). A Servlet Container is a part of a Web Server. A Servlet Container is a separate module; it may run within the web server as a single standalone program (tomcat is one example of it). Now servlet container instantiate a new servlet if not already there and calls its service method in a new child thread. Servlet container wraps the http request in HTTPRequest object and pass it in one of the parameters to service method.
If you're in the case of a apache + tomcat architecture for example, there is a protocol for the connectors (AJP). Have a look at mod_jk and mod_proxy.
When both components (web server and container) are in the same software (tomcat can manage direct http requests), I don't know of the inside implementation. (It was never useful for me, in fact. At the contrary, AJP connectors are commonly used)
Related
I have a java app/client which calls a soap web service using Java Sockets. Now I need to add a load balancer in between the client and server which redirects the request to multiple Tomcat instances where the API is running. How can you establish socket connection from the client without specifying the server port address since the routing happens through the load balancer(F5)? Can this be accomplished through F5 configuration somehow?
For instance the soap url looks like this:
http://abc:1234/myapp/mysoap?wsdl
It needs to be converted to
http://abc/myapp/mysoap?wsdl
I am using embedded jetty and spring for java to java communication over http. My problem is that my server application must handle plain TCP messages also on the same port.
Is there a way to detect if a TCP message arrived which cannot be handled by the servlet?
Thanks for the answers I add some more details:
I cannot modify the client. The reason for this is that the old version of the client uses pure java tcp socket and it turned out that the new server must be backward compatible with the old client.
Have to use the same port
Old client messages are short serialized text over simple socket. 1: open connection, 2: send text, 3: close connection
My server looks something like this: http://kielczewski.eu/2013/11/using-embedded-jetty-spring-mvc/
I do not need to parse the message. It is enough to detect that a message was arrived which is not using http and get the source host name.
You might want to take a look at how to add a custom ConnectionFactory to the ServerConnector of your HTTP port.
This ConnectionFactory concept is how the PROXY Protocol is supported within Jetty currently.
In your case, you might have something like ...
MyTcpConnectionFactory tcpConnectionFactory = new MyTcpConnectionFactory();
ServerConnector http = new ServerConnector(server);
http.addFirstConnectionFactory(tcpConnectionFactory);
server.addConnector(http);
In your case, you would override the newConnection(Connector connector, EndPoint endPoint) method and implement the check for your TCP flow, or the HTTP flow.
If its your flow, you handle the communications on that connection yourself and then throw an IOException when you are done indicating that you don't want jetty to process that connection as HTTP.
Otherwise you return that Connection object to Jetty to process as HTTP.
You are in for a wild ride here my friend. You need to realize that HTTP IS TCP ... its just the content being sent on the TCP socket that classifies it as HTTP or not. That being said, you can intercept the Connection with a filter ie
1) create a filter (google Java Application Server Filters and check the Jetty implementation) for ALL incoming connections
2) check for URI on the request, if it fails, then the request is not HTTP (might want to double check on the request testing logic here)
3) Redirect the request to the appropriate Servlet / Function based on serial socket / http request
On another note, why not use https (port 443) for http and port 80 for your socket requirments ?
I stand corrected. Filters wont work.
In that case, you will have to code a mini firewall. you have to scan all inputs for https headers and redirect accordingly. Can you at least provide some context on the plain TCP messages you want to receive? do you have any control over the sending code ? you do know you can upgrade a TCP/HTTP connection to a websocket (involves client and server) and it will work even better than plain TCP, same port connections, and comes built in Jetty so no custom boiler plates, just a websocket servlet
I have created a Socket Server application that will accept Client connections from other computers on the local network. This is application is run from a public static void main method. and is a very standard java application.
I have also created a web service that runs on tomcat, it also uses java. The web service will http post accept request from any internet connected device.
Once the web service receives a request I would like it to send instructions through the socket server and send some data to the client connected.
I would like to run the socket server applicaiton within the web service so that the web service has access to the socket server without having to connect as a client.
What is the best way to run a standard java app so that the tomcat server will start the application when it starts up? should i run it as a servlet or is there a better way to have the web service access the socket
An application opening its own server socket within a proper application server is pointless and possibly counter productive IMO.
Think about it: Tomcat is probably running on port 8080. Your application is hypothetically going to be running on port 9080. What port do you think clients will need to connect to, to consume your service? And if you answered that correctly, what service/benefit are you then expecting Tomcat to provide you, if your clients are in fact, not going to interact with tomcat at all?
You don't need a (full) application server to run your own personal server. You have the option of:
a Java web service without a web application server, which lets you deploy a full JAX-WS webservice within the vanilla JSE, no application server required
Using the jdk's embedded HTTP server to process your requests
Deploying your standalone application as a windows (or other OS) service
I want to create a web application, which is divided into two part one is client and another is server.
Client:
Client part is on the shared server.
Client is the GWT Application which only use to display data (containing only ui elements and ui events).
Client application is used by server to view and present it's own data.
Server:
The server is the simple java web service (restlet).
The server is reside behind the firewall.
The server contains actual data.
There are N number of servers.
Server does not contains any view if server wants ro view data it will use the gwt client application.
Every server uses same gwt application to view it's own data.
Note :
Client does not contains any address of the server. server will send the request to view it's data.
There is no firewall inbound exception on server firewall to access server data from out side client
I need to communicate client and server through firewall, Is there any architecture or design pattern to implement this type of application?
I don't think that the firewall can bring new restrictions to a GWT application compared with other types of applications (clients).
In case you have the GWT client on one server which makes calls to a different server you might have some issues due to same origin restriction.
This can be resolved in several ways:
- your GWT application has a server-side part which calls the other servers. And your GWT client makes normal RPC / JSON calls to the GWT server side (on the same server).
- in case you want to make directly the call on the different server from your GWT client you can use JSONP or the restygwt library.
We have a number of Jetty http(s) servers, all behind different firewalls. The http servers are at customer sites (not under our control). Opening ports in the firewalls at these sites is not an option. Right now, these servers only serve JSON documents in response to REST requests.
We have web clients that need to interact with a given http server based on URL parameter or header value.
This seems like a straightforward proxy server situation - except for the firewall.
The approach that I'm currently trying is this:
Have a centralized proxy server (also Jetty based) that listens for inbound registration requests from the remote http servers. The registration request will take the form of a Websocket connection, which will be kept alive as long at the remote HTTP server is available. On registration, the Proxy Server will capture the websocket connection and map it to a resource identifier.
The web client will connect the proxy server, and include the resource identifier in the URL or header.
The proxy server will determine the appropriate Websocket to use, then pass the request on to the HTTP server. So the request and response will travel over the Websocket. Once the response is received, it will be returned to the web client.
So this is all well and good in theory - what I'm trying to figure out is:
a) is there a better way to achieve this?
b) What's the best way to set up Jetty to do the proxying on the HTTP Server end of the pipe?
I suppose that I could use Jetty's HttpClient, but what I really want to do is just pull the HTTP bytes from the websocket and pipe them directly into the Jetty connector. It doesn't seem to make sense to parse everything out. I suppose that I could open a regular socket connection on localhost, grab the bytes from the websocket, and do it that way - but it seems silly to route through the OS like that (I'm already operating inside the HTTP Server's Jetty environment).
It sure seems like this is the sort of problem that may have already been solved... Maybe by using a custom jetty Connection that works on WebSockets instead of TCP/IP sockets?
Update: as I've been playing with this, it seems like another tricky problem is how to handle request/response behavior (and ideally support muxing over the websocket channel). One potential resource that I've found is the WAMP sub-protocol for websockets: http://wamp.ws/
In case anyone else is looking for an answer to this one - RESTEasy has a mocking framework that can be used to invoke the REST functionality without running through a full servlet container: http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html_single/index.html#RESTEasy_Server-side_Mock_Framework
This, combined with WAMP, appears to do what I'm looking for.