How to make jersey and #webservlet working together ?
jersey ResourceConfig:
#ApplicationPath("/*")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(Greetings.class);
}
}
jersey Resource registered in resourceConfig:
#Path("/login")
public class Greetings {
#GET
public Response getHelloGreeting(#Context HttpServletRequest httpRequest) {
System.out.println("In the Greetings resource");
String url= "http://"+httpRequest.getServerName()+":"+httpRequest.getServerPort()+httpRequest.getContextPath();
String newURL = url+"/login.jsp";
System.out.println(newURL);
return Response.seeOther(URI.create(newURL)).build();
}
}
web servlet
#WebServlet(name = "LoginServlet", urlPatterns = { "/hello" })
public class LoginServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext servletContext = getServletContext();
System.out.println("inside login servlet");
request.getRequestDispatcher("/login.jsp").forward(request, response);
System.out.println("request forwarded");
}
//other functions not important so deleted
}
Case 1: on accessing this
http://localhost:8088/ResponseFilterweb/login
console logs:
In the Greetings resource
http://localhost:8088/ResponseFilterweb/login.jsp (no ui comes)
on accessing this
http://localhost:8088/ResponseFilterweb/hello
(nothing happens 404 error)
Case 2: Changing application config resource path:
#ApplicationPath("/auth")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(Greetings.class);
}
}
on accessing this
http://localhost:8088/ResponseFilterweb/auth/login
In the Greetings resource
http://localhost:8088/ResponseFilterweb/login.jsp (Ui comes)
on accessing this
http://localhost:8088/ResponseFilterweb/hello
inside login servlet (Ui comes)
userid is
Encoded string
request forwarded
doubts:
don't know why login.jsp is blocked in the first case:
why http://localhost:8088/ResponseFilterweb/login not showing any ui .. i think it should come ?
why http://localhost:8088/ResponseFilterweb/hello not showing any ui ?
If you were using web.xml, this or this would be your solution, but since you're not, this might be your only option. The problem is that when you use /* as the servlet mapping for Jersey, it hogs up all the requests. So the request to /hello would go to Jersey and not the LoginServlet. What those solutions I linked to do is cause Jersey to forward the request if it can't find it within the Jersey application. The other solution is to just change the servlet mapping to something like /api/* (which is pretty common), then you would just prefix your API requests with /api.
Using asterisk (*) won't work using #ApplicationPath
If you use /*, then you're making it too greedy and saying it should match everything all the time, and the default servlet will never be invoked
Use #ApplicationPath("/") instead
If you use /, then you're replacing the container's default servlet
Related
Basically I have servlet named forward. When a request is made to it, it forwards the request to a .html file like this:
#WebServlet("/forward")
public class forward extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/videos/forward.html").forward(request, response);
return;
}
}
The problem is that when I test this on eclipse when a request is made to this servlet, it responds with the link as localhost/videos/forward.html
But then when I deployed it with name com.war Now when a request is made to it, it responds with localhost/com/videos/forward.html
How can I make the requestDispatcher to respond with localhost/videos/forward.html and not as localhost/com/videos/forward.html
No you cannot. Forwarding is a request made to the servlet container to pass control to another servlet in same servlet context. A JSP page in indeed implemented as a servlet, but a HTML is just a ressource, so you cannot forward to it.
But you can redirect to it. A redirection works by sending a special response telling the browser that it should go to that other URL. As it works at browser level, you can redirect to a HTML page or even to a completely different site.
You can use the sendRedirect method from HttpServletResponse to initiate a redirection from a servlet:
#WebServlet("/forward")
public class forward extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("/videos/forward.html");
return;
}
}
Just write
response.sendRedirect(pagename.html)
Yes, u can.
use:
RequestDispatcher r = req.getRequestDispatcher(String arg);
I want to hide the Apache Camel Servlet behind Spring MVC Controller entry point, because I have some proprietary components I have to use that depend on Sping Boot and Spring MVC Controller.
I have the following Apache Camel Route, which is working fine
<route id="Route">
<from uri="servlet:messages?httpMethodRestrict=POST"/>
<process ref="..."></process>
<to uri="{{storage.service.endpoint}}?bridgeEndpoint=true"/>
</route>
I have registered the Camel Servlet without any URL mappings, because I don't want to be accessible directly. The Spring Bean:
#Bean
ServletRegistrationBean servletRegistrationBean() {
CamelHttpTransportServlet camelServlet = new CamelHttpTransportServlet();
ServletRegistrationBean servletBean = new ServletRegistrationBean(camelServlet, false, new String[]{});
servletBean.setName("CamelServlet");
return servletBean;
}
In Spring Controller Entry point I just need to forward to Camel Servlet:
#RequestMapping(method=RequestMethod.POST, value="/api/v1/*")
public void wrapper(HttpServletRequest request, HttpServletResponse response) throws Exception{
context.getNamedDispatcher("CamelServlet").forward(request, response);
}
The problem is that Camel Servlet relies on ServletResolveConsumerStrategy using request.getPathInfo(), which is always null in Spring Controller entry point. I have tried different paths in #RequestMapping, but always request.getServletPath() has the full path and the pathInfo is null
P.S. The application is running on Tomcat 8.
Modify the Spring Controller entry point using path variables and set the value of the path variable a pathInfo() in a custom HttpServletRequestWrapper:
#RequestMapping(path="/api/v1/{messages}" , method=RequestMethod.POST)
public void wrapper2(HttpServletRequest request, HttpServletResponse response, #PathVariable String messages) throws Exception{
request = new PathInfoRequestWrapper(request, messages);
context.getNamedDispatcher("CamelServlet").forward(request, response);
}
class PathInfoRequestWrapper extends HttpServletRequestWrapper{
private String pathInfo;
public PathInfoRequestWrapper(HttpServletRequest request, String pathInfo) {
super(request);
this.pathInfo = pathInfo;
}
#Override
public String getPathInfo(){
String origPathInfo = super.getPathInfo();
if(origPathInfo == null || origPathInfo.equals("")){
return this.pathInfo;
}else{
return origPathInfo;
}
}
}
One solution is to create custom ServletResolveConsumerStrategy, which relies only on request.getServletPath(), to find the appropriate route. Unfortunately only setting the Strategy with org.apache.camel.http.common.CamelServlet.setServletResolveConsumerStrategy(ServletResolveConsumerStrategy) does not work, because the it is overwritten in org.apache.camel.component.servlet.CamelHttpTransportServlet.init method. SO you need to override the init in the Camel Servlet as well:
CamelHttpTransportServlet camelServlet = new CamelHttpTransportServlet(){
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletResolveConsumerStrategy servletResolveConsumerStrategy = new CamelSpringResolveConsumerStrategy();
setServletResolveConsumerStrategy(servletResolveConsumerStrategy );
}
};
For a WebApp, I need to serve all .js, .css and all images from corresponding folders in my web app development tree ./js, ./css, ... through a default handling.
So any URL like
http://www.example.com/js/x.js
should be served straight from the static files in the war.
The main servlet should deal with all requests that are not for the above.
I need to be able to process requests like
http://www.example.com/PROJ/ELEM/WHATEVER
with the same unique main servlet.
So I thought I'd do this in the web.xml:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/css/*,/js/*,/WEB-INF/*</url-pattern>
</servlet-mapping>
and map the main servlet like this to make some JSTL mods in a JSP file:
#WebServlet(urlPatterns="/*")
public class Main extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("test", "ok");
request.getRequestDispatcher("/WEB-INF/index.jsp")
.forward(request, response);
}
}
When I do this I end up in a recursive loop.
Is there a way to achieve this?
Here is the explanation with same problem.
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
This is what already happens. There is a 'default servlet' that handles any request that isn't specifically mapped to an installed servlet.
A simple variation on Rahul Jain's answer. You could do what spring MVC does for static resources : DispatcherServlet is a catch all, and it is configured to delegate to default servlet for a number or url. This may be interesting for a catch all servlet because it is often designed as a front controller that delegates actual serving to other controllers (be them servlets or not).
You can simply give the prefixes of urls that should serve static resources in a comma separated string in a context param of name static_path_prefixes and put that in your servlet :
String[] staticPathPrefixes;
RequestDispatcher defaultDispatcher;
#Override
protected void service(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
String path = hsr.getServletPath();
for (String url: staticPathPrefixes) {
if (path.startsWith(url)) {
defaultDispatcher.forward(hsr, hsr1);
return;
}
}
super.service(hsr, hsr1);
}
#Override
public void init() throws ServletException {
String urls = getServletConfig().getInitParameter("static_path_prefixes");
staticPathPrefixes = urls.split(" *, *");
defaultDispatcher = getServletConfig().getServletContext().
getNamedDispatcher("default");
}
Is there a way to secure a forward URL?
To be clear, I've an error handler:
#Component
public class MyAuthenticationFailureHandler implements
AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (exception.getClass().isAssignableFrom(
MyException.class)) {
MyException myException = (MyException) exception;
RequestDispatcher dispatcher = request.getRequestDispatcher("/signup/exception");
request.setAttribute("userID", myException.getUserID());
dispatcher.forward(request, response);
}
}
}
and a web controller:
#Controller
#RequestMapping("/signup")
public class SignupController {
#RequestMapping("/exception")
public ModelAndView signup() {
ModelAndView model = new ModelAndView(new InternalResourceView("/WEB-INF/jsp/signup.jsp", true));
return model;
}
}
I'd like that the route http://{hostname:port}/signup/exception will be accessible only as forward from my own handler, not directly (by writing URL and params on browser bar).
Add an attribute like
request.setAttribute("isForwarded","True")
in handler and check that attribute inside your controller.
If yes, go ahead else redirect to appropriate page.
I didn't test it, but I know that servlet containers refuse to answer to request relative to WEB-INF, but that you can forward to jsp servlets under WEB-INF. May be you could try to use an url like /WEB-INF/signup/exception ?
Alternatively, I think you're using Spring Security. I do not think that security filters are applied to forwarded requests. What gives the following intercept-url ?
<intercept-url pattern="/signup/exception" access="denyAll" />
I have a filter which processes requests in order to log them, so I can keep track of which session hit a page at what time with what request parameters. works great... posting from jsp to jsp, or making a direct call to a jsp. When a form is posted to a servlet which forwards that request to a new jsp, however, I am unable to see which jsp the request was forwarded to.
For example, suppose I have a login page, which posts to a LoginServlet, which then forwards the request to either index.jsp or index1.jsp. How can I determine from the request whether LoginServlet is returning index.jsp or index1.jsp?
This is in a java 1.5 environment using the 2.3 servlet specification.
public class PageLogFilter implements Filter {
FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
if (request instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession(false);
//For non-forwards, I can call req.getRequestURI() to determine which
//page was returned. For forwards, it returns me the URI of the
//servlet which processed the post. I'd like to also get the URI
//of the jsp to which the request was forwarded by the servlet, for
//example "index.jsp" or "index1.jsp"
}
} catch (Exception e {
System.out.println("-- ERROR IN PageLogFilter: " + e.getLocalizedMessage());
}
chain.doFilter(request, response);
}
}
If you are OK with performing an additional check then you can use attribute to set/get original request URI.
In your LoginServlet set the attribute:
//LoginServlet
public void doFilter(...) {
HttpServletRequest oReq = (HttpServletRequest)request;
..
...
//save original request URI
oReq.setAttribute("originalUri", oReq.getRequestURI());
}
and in your PageLogFilter check if originalUri attribute has value then consider this value as the request URI
//PageLogFilter
public void doFilter(...) {
HttpServletRequest req = (HttpServletRequest) request;
if(req.getAttribute("originalUri") != null) {
String strOriginalUri = (String) req.getAttribute("originalUri");
//set it back to null
req.setAttribute("originalUri", null);
}
}
Although it wont help solve your immediate problem, Servlet 2.4 added further detailed control on the dispatcher, which is what you want.
With it, you can configure the filter to add the following dispatcher element, which would cause the filter to also apply to forwards.
<filter-mapping>
<filter-name>PageLogFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The following article explains it in more detail
http://www.ibm.com/developerworks/java/library/j-tomcat2/