I have set up an embedded Jetty server with a filter to add some headers to every request.
MainHandler mainHandler = new MainHandler();
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
servletContextHandler.setContextPath("/application");
servletContextHandler.setHandler(mainHandler);
servletContextHandler.setAllowNullPathInfo(true);
servletContextHandler.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST, DispatcherType.INCLUDE, DispatcherType.FORWARD));
Mainhandler is the class which processes the requests.
The init() method of the filter is called, but not the doFilter() Method thus my filter is not applied. I tried it with "/application/something".
Can anybody help me please?
Don't mix Handlers and ServletContextHandler's like that.
That's not what the ServletContextHandler.setHandler(Handler) is for.
Change your MainHandler to extend from HttpServlet and add it to the ServletContextHandler.addServlet().
Your MainHandler is preventing correct dispatch of the request into the ServletContextHandler.
This is because ServletContextHandler.setHandler() is for the management of things outside of the ServletContext and the specific request chain (such as session management, security management, gzip encoding management, request logging management, etc), not for actually processing a request and producing a response within that ServletContext. The ServletContextHandler.setHandler() is meant for managing state and scope within an exchange (request, response, inputs, outputs, sessions, security, etc), with all valid implementations being a ScopedHandler that is ServletContext, Context, and ServletContextHandler aware.
Look at this example of the official documentation:
package org.eclipse.jetty.embedded;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
public class MinimalServlets
{
public static void main( String[] args ) throws Exception
{
// Create a basic jetty server object that will listen on port 8080.
// Note that if you set this to port 0 then a randomly available port
// will be assigned that you can either look in the logs for the port,
// or programmatically obtain it for use in test cases.
Server server = new Server(8080);
// The ServletHandler is a dead simple way to create a context handler
// that is backed by an instance of a Servlet.
// This handler then needs to be registered with the Server object.
ServletHandler handler = new ServletHandler();
server.setHandler(handler);
// Passing in the class for the Servlet allows jetty to instantiate an
// instance of that Servlet and mount it on a given context path.
// IMPORTANT:
// This is a raw Servlet, not a Servlet that has been configured
// through a web.xml #WebServlet annotation, or anything similar.
handler.addServletWithMapping(HelloServlet.class, "/*");
// Start things up!
server.start();
// The use of server.join() the will make the current thread join and
// wait until the server is done executing.
// See
// http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()
server.join();
}
#SuppressWarnings("serial")
public static class HelloServlet extends HttpServlet
{
#Override
protected void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException
{
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello from HelloServlet</h1>");
}
}
}
Related
Is there a way that I can listen to any particular request without that request being present in any of the request mappings in Spring ? I am trying to build a gateway functionality where i need to redirect a request to a downstream API by inspecting the request URI. I would need to see if I have the downstream/internal api for that particular request and forward to the downstream API if i have that mapping.
I currently have all the downstream mapping in the database.
For example:
Client facing uri: http://external_host/api/xyz/
downstream uri: http://downstream_host/api/abc
I store this mapping of client facing uri and downstream uri in the database. So I just to want to listen to all the requests that are hitting my service and then examine on my own if I can forward the request or not based on the mapping I have stored.
All I could think was to have a controller that would accept any request but I do not like this approach as this seems pretty naive.
#RestController
#RequestMapping(value = "*")
public class TestController {
#RequestMapping(value = "/*", method = RequestMethod.GET)
public void GetRequestUri() {
System.out.println("test");
}
}
I hope my question was elaborate enough.
You could use Netflix Zuul which is a proxy that is doing routing and filtering, but with a different way.
If you want to build your own proxy - discovery service you need to use only one endpoint, so your implementation has nothing wrong!
Approach - Creating a filter
Reference: How to register a servlet filter in Spring MVC
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class RootFilter implements Filter {
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
// Evaluate the request path
chain.doFilter(request, response);
} catch (Exception ex) {
//handle Exceptions.
}
}
}
web.xml
<filter>
<filter-name>RootFilter</filter-name>
<filter-class>com.....RootFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RootFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Filter[] getServletFilters() {
return new Filter[]{new RootFilter()};
}
}
Approach - Creating Interceptor
Reference: Spring 3 MVC Interceptor tutorial
Spring MVC provides a powerful mechanism to intercept an http request. Similar to Servlet Filter concept, Spring MVC provides a way to define special classes called Interceptors that gets called before and after a request is served.
Each interceptor you define must implement org.springframework.web.servlet.HandlerInterceptor interface. There are three methods that need to be implemented.
preHandle(..) is called before the actual handler is executed;
The preHandle(..) method returns a boolean value. You can use this method to break or continue the processing of the execution chain. When this method returns true, the handler execution chain will continue; when it returns false, the DispatcherServlet assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.
postHandle(..) is called after the handler is executed;
afterCompletion(..) is called after the complete request has finished.
These three methods should provide enough flexibility to do all kinds of preprocessing and postprocessing.
I am developing server side web services code. I am using JAX-RS as development framework.
So far I have created model classes and resources class that responds requested data to client.
Sample resource method...
#GET
#Path("/{userId}")
#Produces(MediaType.APPLICATION_JSON)
public User getUserDetails(#PathParam("userId") long id) {
..
// some code here //
..
}
Basically, server responds the data or do some operations depends on the URI is been called by the client.
I want to make Http POST request to third-party server at every two minutes from the moment server starts. But I dont know where should I write that code (as I said, methods executions depends on the URI is been called).
So, where should I write the code that starts executing when the server starts and ends when server stops.
How to send Http request at every two minutes interval ?
You should be able to do that with a combination of Quartz and ServletContextListener.
You will need to create a job, trigger and scheduler to make your code run after every two minutes and a listener class that implements ServletContextListener interface.
Your code would look something like this:
Job Class:
package com.example;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class ExampleJob implements Job
{
public void execute(JobExecutionContext context) throws JobExecutionException {
// Code to make POST call here
}
ServletContextListener
package com.example;
public class ExampleListener implements javax.servlet.ServletContextListener {
public void contextInitialized(ServletContext context) {
JobDetail job = JobBuilder.newJob(ExampleJob.class)
.withIdentity("exampleJob", "group").build();
// Trigger
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("exampleTrigger", "group")
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(120).repeatForever())
.build();
// Scheduler
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
}
}
And add this in web.xml:
<listener>
<listener-class>com.example.ExampleListener</listener-class>
</listener>
or if you are using servlet container 3.x, you can skip the web.xml modification by annotating the listener class with #WebListener
I am new to Jetty and trying to understand by online example program. Here is the sample program I used:
public class EmbeddedJettyMain {
public static void main(String[] args) throws Exception {
Server server = new Server(7070);
ServletContextHandler handler = new ServletContextHandler(server, "/example");
handler.addServlet(ExampleServlet.class, "/");
server.start();
}
}
With that I can use:
http://localhost:7070/example/
Now I want to add one more servlet URI
http://localhost:7070/example2
How can I do this ?
I can see some reference such as webapp, looking for a good approach.
Server server = new Server(7070);
ServletContextHandler handler = new ServletContextHandler(server, "/");
handler.addServlet(ExampleServlet.class, "/example");
handler.addServlet(ExampleServlet.class, "/example2");
Each addServlet creates a mapping. Jetty will create an instance of the Servlet that will be a singleton for each mapping, meaning that init(ServletConfig config) will only be called once in each instance and all requests to a mapping go to the same instance.
Jetty provides a Web server and javax.servlet container.
Your servlets are stored and served via jetty's embedded container to serve when needed.
I have a class which implements the ClientRequestFilter for the Client-side filtering.
import java.io.IOException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.client.ClientRequestFilter;
import org.glassfish.jersey.server.ContainerRequest;
#Provider
public class checkRequestFilter implements ClientRequestFilter{
#Override
public void filter(ClientRequestContext clientRequestContext) throws IOException {
System.out.println("I am in checkResponseFilter");
}
}
But I don't know what to do so that I will be able to call this filter?
Do we need to add some kind of servlets in web.xml ?
A ClientRequestFilter acts on the client side. Thus, you don't have to add it to the servlet, but to the client (assuming you are using Jersey client API).
When you build your client you do something like this:
Client client = ClientBuilder.newClient();
client.register(new CheckRequestFilter()); // your filter
// more filters
WebTarget target = client.target(....
You can find a nice example over here on authentication support:
https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/client.html#d0e5464
and this one on filters
https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/client.html#d0e4391
If you meant to use a filter on the server side, you need to use ContainerRequestFilter.
Another option to do this:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
cb = ClientBuilder.newBuilder();
client = cb.register(new checkRequestFilter()).build();
Also note that this is a client side filter, so you are trying to filter a request (not a response) that you send (hence you register the filter on your client).
I have this code,
#WebServlet(value="/initializeResources", loadOnStartup=1)
public class InitializeResources extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("HEREEEE");
}
}
But the servlet doesn't start when the web application is started.
How use load on startup on Servlet Annotation?
My Servlet API is 3.0 and I use Tomcat 7
With you current code, you need to do a GET request for see the output HEREEEE.
If you want to do something on the startup of the servlet (i.e. the element loadOnStartup with value greater or equal to zero, 0), you need put the code in a init method or in the constructor of the servlet:
#Override
public void init() throws ServletException {
System.out.println("HEREEEE");
}
It may be more convenient to use a listener to start a resource in the application scope (in the ServletContext).
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
#WebListener
public class InitializeListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("On start web app");
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("On shutdown web app");
}
}
For an example, see my answer for the question Share variables between JAX-RS requests.
#WebServlet(name="InitializeResources", urlPatterns="/initializeResources", loadOnStartup=1)
urlPatterns to be ensure that the web conatainer finds the servlet path.
When loadOnStartup is specified for a Servlet, the container would only load and pre-instantiate an instance of your Servlet ready to process any GET/POST requests that may come. This by itself wouldn't cause doGet() or doPost() to get fired because an actual client request hasn't come for processing yet. So, what's its use then?
Well, loadOnStartup is typically used for Servlets that have heavy initialization code; say, they may make a JNDI call to get hold of a resource or a Database call to populate a local data structure with some backend values. In the absence of loadOnStartup the very first client request could be painfully slow because of all this extra initialization stuff and hence pre-instantiating it makes sense.
Now, your custom initialization code (JNDI, JDBC) would go in an overriden GenericServlet#init() method which is called by the servlet container to indicate to a servlet that it's being placed into service.