HTTP method GET is not supported by this URL - java

I'm calling servlets which has implemented CometProcessor interface, and whenever I try to call the servlets with get request, I'm getting the above error. May I know the reason?
public class ChatServlets
extends HttpServlet implements CometProcessor {
public void event(CometEvent event)
throws IOException, ServletException {
HttpServletRequest request = event.getHttpServletRequest();
HttpServletResponse response = event.getHttpServletResponse();
if (event.getEventType() == CometEvent.EventType.BEGIN) {
response.getWriter().println("Welcome ");
} else if (event.getEventType() == CometEvent.EventType.READ) {
response.getWriter().println("Bye");
}
}
}

From this document:
IMPORTANT NOTE: Usage of these features requires using the APR or NIO HTTP connectors. The classic java.io HTTP connector and the AJP connectors do not support them.
By default you get classic java.io HTTP connector configured in your server.xml. Have you changed it to NIO connector?

Related

SlingServletFilter: Get status code before doFilter

I'm trying to make unexisting pages under my domain go to a 404 page. I need to distinguish 404 pages from the other pages. However, I do not know how to do this. And the thing below is not working.
#Component(service = Filter.class,
property = {
"service.ranking=" + Integer.MIN_VALUE})
#SlingServletFilter(scope = {SlingServletFilterScope.REQUEST},
pattern = "/content/foo/.*",
resourceTypes = "cq:Page",
extensions = {"html"},
methods = {"GET"})
public class NotFoundFilter implements Filter {
private static final String DEFAULT_METHOD = "GET";
#Reference
private UrlOperationsManager urlOperationsManager;
#Reference
private RequestResponseFactory requestResponseFactory;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!(request instanceof SlingHttpServletRequest) ||
!(response instanceof SlingHttpServletResponse)) {
chain.doFilter(request, response);
return;
}
SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
//this condition here is not working since slingResponse has no getStatusCode method.
if(slingResponse.getStatusCode() == 404) {
//do something
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
You could work around this by implementing your own HttpServletResponseWrapper to save the value and access it later. The Sling implementation is marginally different (at least as far as this particular mechanic is concerned) from the generic Servlet API, which is covered in depth in How can I get the HTTP status code out of a ServletResponse in a ServletFilter?
However, if your intention is to serve a particular error document for a given status code, I'd approach it differently. Assuming you use a Dispatcher, you could have the web server take care of it.
The official AEM project archetype comes with a few simple examples that you could enable if you use Apache. The details will depend on your site structure but the gist is that it's possible to provide a similar configuration using the ErrorDocument directive to point to a cached error page relative to the document root, usually making it use content-editable error pages.
Some errors, especially HTTP 5** family could be a bit more tricky that way in that they usually happen when there's something wrong with AEM itself so it's prudent to make sure a fully static version is always available.

Jetty: Find out which connector was used for incoming Request

When handling a Jetty response I want to know on which port the request originated on?
public static void main(String[] args) {
Server server = new Server();
server.setConnectors(new Connector[] {connectorUnsecure, connectorSecure});
ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath("/");
handler.addServlet(MyServlet.class, "/*");
server.setHandler(handler);
server.start();
server.join();
}
public abstract class MyServlet extends HttpServlet {
#Override
protected final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Find out on which connector port the request came from.
// (The request.getRequestURL() does not contain the port at all times.)
}
}
When using a custom Handler, I could use something like:
public class CustomHandler extends AbstractHandler {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// baseRequest.getConnection().getConnector().getPort()
}
}
However, I don't want to use a custom handler.
Is it possible to obtain the connector and its port when using a plain HttpServlet?
Thanks!
There's 5 methods on javax.servlet.http.HttpServletRequest that might be of use for you.
.getLocalAddr() - the server address the request is being processed on (could be IPv4 or IPv6)
.getLocalPort() - the server port the request is being processed on
.getRemoteAddr() - the client address the request is being processed on (could be IPv4 or IPv6)
.getRemotePort() - the client port the request is being processed on
.getHeader("Host") - the requested HTTP Host (and port) that the client thinks its talking to. (part of the HTTP spec, and especially useful for virtual hosts)
Note: the HTTP Request Host header can also be obtained via the .getRequestURI() method.
String serverAddr = URI.create(request.getRequestURI()).getHost();

What is the equivalent of an apache module in java server technology

I have a task to examine incoming HTTP requests and do some processing on the header and request body then store that locally.
If I understand correctly, I can do that with an apache module for Apache servers and an IIS extension for IIS. I'm not clear on what I would use for Java based application servers.
Any help/guidance would be appreciated.
If you will use a Java application server, then you should handle this in a Servlet Filter. Here's an example:
#WebFilter("/app/*")
public class LoginFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
//Set init params and load any resources to be used in this class.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
//Here you will pre and post process the request-response cycle.
//Pre process is before executing "chain.doFilter(req, res);"
//Post process is after executing "chain.doFilter(req, res);"
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
String someRequestHeader = request.getHeader("<header-you-want-or-need>");
//do what you need to do
chain.doFilter(req, res);
}
#Override
public void destroy() {
//Close/free any resources used in this class.
}
}
More info:
The Java EE 7 Tutorial. 17 Java Servlet Technology. 17.6 Filtering Requests and Responses
Maybe you could use a HttpServlet.
Also have a look at the tutorial.

How can I get my hands on client addresses for logging using Grizzly / Jersey?

I'm using Grizzly to serve a Jersey application, while using Logback for my logging needs. Please not that there are no Servlets involved here, I fire up everything "by hand" using a piece of code like this:
final URI uri = /* this is a configuration option */
this.server = new HttpServer();
final NetworkListener nl = new NetworkListener(
"grizzly", uri.getHost(), uri.getPort());
server.addListener(nl);
final GuiceComponentProviderFactory gcpf =
new GuiceComponentProviderFactory(rc, inj);
final HttpHandler processor = ContainerFactory.createContainer(
HttpHandler.class, rc, gcpf);
this.server.getServerConfiguration().addHttpHandler(
processor, uri.getPath());
server.start();
Now I would like to use Logback's MDC feature to make the socket address of the clients visible in the log records. For this purpose I would need some place to hook up a listener to the HTTP processing which gets notified about incoming requests (where I can put the address into the MDC) and when a request is done (so I can clean up the MDC). One approach I followed is to hook up a Container*Filter instance with Jersey, which looked like this:
class MdcFilter implements
ContainerRequestFilter, ContainerResponseFilter {
#Override
public ContainerRequest filter(ContainerRequest request) {
MDC.put("http-client", "foo" /* no way to get the address here */);
return request;
}
#Override
public ContainerResponse filter(
ContainerRequest request,
ContainerResponse response) {
MDC.remove("http-client");
return response;
}
}
Unfortunately, a Jersey ContainerRequest does not provide information about the connected client (which cam as a real surprise).
I suspect a similar interface should exist with Grizzly itself, but I was unable to dig it out.
For Grizzly, the relevant API is called HttpServerProbe. Using this, it comes down to something like this:
final HttpServer server = new org.glassfish.grizzly.http.server.HttpServer();
server.addListener(new NetworkListener("grizzly", "localhost", 8080));
server.getServerConfiguration().addHttpHandler(
new StaticHttpHandler("/var/www/"), "/");
server.getServerConfiguration().getMonitoringConfig().getWebServerConfig()
.addProbes(new HttpServerProbe.Adapter() {
#Override
public void onRequestReceiveEvent(
HttpServerFilter filter,
Connection connection,
Request request) {
System.out.println(request.getRemoteAddr());
MDC.put("http-client", request.getRemoteAddr());
}
#Override
public void onRequestCompleteEvent(
HttpServerFilter filter,
Connection connection,
Response response) {
MDC.remove("http-client");
}
}
server.start();
Note that there are more events which might be relevant, like suspend, resume and cancel. These should probably be handled as well, especially if long-polling (aka Comet, aka whatnot) is used. But basically this is the place to hook into.
In your MdcFilter, try to inject the HttpServletRequest into your class and use that as you would normally to call getRemoteAddr() or any other such function as in:
class MdcFilter implements
ContainerRequestFilter, ContainerResponseFilter {
#Context
protected HttpServletRequest r;
#Override
public ContainerRequest filter(ContainerRequest request) {
MDC.put("http-client", "foo" r.getRemoteAddr());
return request;
}
#Override
public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
MDC.remove("http-client");
return response;
}
}
I tested this out using a similar approach to "firing things up by hand" and it worked out for me in that case. I assume it would work for you as well.

How do I handle error states in servlet filters without showing the user a stack trace?

I'm working on a Jetty/RESTEasy app. If I throw a WebApplicationException(myResponse) from one of my REST endpoints, it sends the given response to the client.
When a filter detects an error, I want the same behavior:
It should stop execution from proceeding, and
It should give the user a clear, JSON-formatted error that does not include a stack trace.
Obviously, just writing to the response stream and returning works from within the doFilter method. But this doesn't work for other methods called by doFilter.
Throwing any exception will meet condition #1 but I haven't figured out a sane way to meet condition #2 then. (You can see my best attempt at the bottom.)
As Perception explained in his answer, WebApplicationExceptions are treated like any other exception in the context of a Filter, and therefore give the user a nice ugly stack trace.
So, to sum up my questions:
Do serveltt containers have any equivalent to throw new WebApplicationException(Response)?
And perhaps more importantly, how do other java projects handle this?
I have this code in one filter and it works, but I'd prefer a more elegant solution that automatically applies to all filters:
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
try {
doFilterOrThrow(request, response, chain);
} catch (WebApplicationException e) {
Response res = e.getResponse();
((HttpServletResponse) response).sendError(res.getStatus(), (String) res.getEntity());
}
}
The specific handling you mention for web application exceptions is only defined within the context of a JAX-RS container, which, by the way, is not the same thing as a Servlet container.
Web filters are handled by the Servlet container, which does not know or care that a JAX-RS container exists within the same application server. It also does not know or care about web application exceptions. So when you throw the WAE from within the filter it is treated just the same as any other exception (server error with a stack trace, or a preconfigured error page if you set one up in your web application).
It would seem to me if you are indicating an error to the client you could simply do so from the filter, by writing directly to the response stream. But if you are trying to leverage some existing JAX-RS logic then a (RESTEasy specific) solution would be to flag the request as error'ed out in your filter, then generate a WAE in JAX-RS, using a provider class. Example:
#WebFilter(urlPatterns = "*")
public class ForwardingFilter implements Filter {
#Override
public void destroy() {
return;
}
#Override
public void doFilter(final ServletRequest request,
final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
// Add an error response to be processed by the JAX-RS container.
// This would obviously be based on some condition.
request.setAttribute("errorResponse",
Response.status(500).entity("Didn't work out!").build());
chain.doFilter(request, response);
}
#Override
public void init(FilterConfig arg0) throws ServletException {
return;
}
}
#Provider
#ServerInterceptor
#HeaderDecoratorPrecedence
#RequestScoped
public class ForwardingHandlerProvider implements PreProcessInterceptor {
#Override
public ServerResponse preProcess(final HttpRequest request,
final ResourceMethod method) throws Failure,
WebApplicationException {
final Response errorResponse = (Response) request
.getAttribute("errorResponse");
if (errorResponse != null)
throw new WebApplicationException(errorResponse);
return null;
}
}
Since the provider exists in JAX-RS land, the web application exception is processed according to the rules of Section 3.3.4 of the JAX-RS specification, and you get the desired response at the client side.
* EDIT:*
The bottom line is, there is no standard Java EE prescribed way (currently) to handle servlet exceptions in a centralized fashion similar to what is available in JAX-RS. Since you are using JBoss/RestEASY though, you could utilize the JBoss Seam Catch library to get pretty close.
#HandlesExceptions
public class ExceptionHandler {
public void handleServletException(
final #Handles #WebRequest CaughtException<ServletException> caught,
#Context final HttpServletResponse response) {
try {
response.sendError(500, "An error occured");
} catch (final IOException ioe) {
System.err.println("Dumb IO Exception: " + ioe);
}
}
}
The above illustrates an exception handler, as described in the Seam Catch documentation. Note that the library is in massive flux right now, so you will want to utilize it only as a last resort.

Categories

Resources