Forwarding request to a JSP - java

I discovered Guice last week... I'm trying some easy tricks with it. However, I'm currently blocked...
I'm trying to forward a request to a JSP in a Servlet served by an url-pattern which contains a " * ". But I receive "Error 404" all the time :(
Step by Step :
ServletModule :
serve("/test/*").with(TestServlet.class);
TestServlet :
public void doGet(HttpServletRequest req, HttpServletResponse resp)
{
System.err.println("Start");
try
{
req.getRequestDispatcher("/WEB-INF/layout/test.jsp").forward(req, resp);
}
catch (Exception e)
{
e.printStackTrace();
}
}
I get this error :
HTTP ERROR 404
Problem accessing /WEB-INF/layout/test.jsp. Reason:
/WEB-INF/layout/test.jsp
I tested with "serve("/test").with(TestServlet.class);" and it worked
I tested without Guice (by defining servlet in the web.xml) and it worked...
What did I do wrong?
Thank for reading!

Client can't access resources from Web-INF directly (by url). So forwarding doesn't work in this case. But your servlets can. So just use include instead of forward.

There's a good chance you didn't do anything wrong at all. There is a bug in Guice, arising from their mishandling of Include and Forward attributes against servlet standards, as described here...
http://code.google.com/p/google-guice/issues/detail?id=647
The upshot is that the receiving servlet is misinformed about the path, and hence requests to load resources do not find their proper target even if they are specified correctly and even if the same code works when using web.xml (which is interpreted by your servlet engine and not by Guice).
I'm endlessly puzzled why this doesn't act as a dead-end for many many projects in Guice, so perhaps there's something in the behaviour of other servlet engine configurations which masks this error. I'm using Jetty launched explicitly in Java using Server#start(); and it is a deal-breaker for a lot of server logic.
However, the Guice team seems to have been studiously ignoring the bug for a long time, even when a patch was provided to them against v2.0. What they need is a test-case written against their SVN build but I've never succeeded given all the work needed to create stubs which emulate the servlet engine and so on.

The problem has been partially fixed in guice and guice servlet 3.1.1 with one problem still taking place:
When mapping a servlet using the asterisk pattern '/*' as below:
serve("/myservlet/*").with(MyServlet.class);
And have MyServlet.java forward to a jsp page, then the forward() will only work if the jsp page has no underscores (So, myservlet.jsp will work, my_servlet.jsp wont work).
// This WORKS
req.getRequestDispatcher("/myservlet.jsp").forward(req,resp);
// These DONT WORK (any file having _ or - characetsrs wont work)
req.getRequestDispatcher("/my_servlet.jsp").forward(req,resp);
req.getRequestDispatcher("/my-servlet.jsp").forward(req,resp);
req.getRequestDispatcher("/WEB-INF/myservlet.jsp").forward(req,resp);
Now this explains why WEB-INF forwarding does not work for a servlet mapped with /*. The reason is that WEB-INF contains a dash character which for some reason is creating a problem for guice servlet.
When trying the example above, make sure to rename the file myservlet.jsp to my_servlet.jsp when trying the cases to verify the case above.
I have no idea why this weird case is taking place.
NOTE: I'm using Tomcat 6.0.35
To have Guice 3.1.1 add these to your pom.xml
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-guice</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.sonatype.sisu.inject</groupId>
<artifactId>guice-servlet</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.sonatype.sisu.inject</groupId>
<artifactId>guice-assistedinject</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
Or you can download the jars from:
Guice Servlet Jar
http://repo1.maven.org/maven2/org/sonatype/sisu/inject/guice-servlet/3.1.1/
Guice Jar
http://repo1.maven.org/maven2/org/sonatype/sisu/sisu-guice/3.1.1/

Related

Unable to display index.html in jax rs with spring boot

I am trying to create a simple app with jax rs, springboot, angular.
I have placed the index.html in static folder, but while hitting the url localhost:8080/index.html or localhost:8080 it's throwing 404 not found error through the custom exception handler. I have added index.html as welcome-file-list.
I have a controller class but i have not written any specific method to handle it.
Also i want to display error specific page with message details.
Definitely i am missing something but not getting any pointer to find it out. Please help.
Do i need to configure web.xml explicitly for this?
Add
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
To your pom.xml file, spring boot auto configure all the rest.
I know this is older, but to expand on Itsik's answer I found this answer via this other answerto be very helpful in explaining this.
Summed up, if you want to be able to serve up resources/static/index.html AND use JAX-RS/jersey for api endpoints, include both spring-boot-start-web and spring-boot-starter-jersey. In your JerseyConfig add #ApplicationPath("/api") or whatever subpath you want all your jax-rs rest endpoints to live under. Then you will be able to have the best of both worlds.

How to make a server wide filter on Tomcat?

At work, we've inherited this Java class which handles all SSO login operations. There's a FiltroSegurancaGlobal.class which is mapped to *, forcing everything with a annotation
#WebFilter(urlPatterns = { "/*" })
The class is deployed in a JAR with a few other classes to handle the whole SSO operation.
Recently I was requested to install and configure a git server for internal purposes, I found a really interesting solution GitBlit, which works like a charm.
Here's the thing, when I deployed it to the server somehow some requests are slipping through the filter. That seemed impossible so I changed the filter to nothing:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("filter hit");
}
While the whole application wasn't being loaded, the user wasn't being redirected to the log in page, none of the resources (css,js) were loaded, but the (index) still shows in the developer tools windows with some of the page.
How is this possible? Wasn't a deployed filter with "/*" urlPatterns supposed to filter ALL requests?
As mentioned bellow I tried changing the urlPatters using annotation first, then server's web.xml later:
#WebFilter({"/", "*", "/*"})
and then
<filter-mapping>
<filter-name>FiltroSegurancaGlobal</filter-name>
<url-pattern>/*</url-pattern>
<url-pattern>*</url-pattern>
<url-pattern>/</url-pattern>
</filter-mapping>
Nothing has changed.
By probing chrome I realized that the only file that seemed to come through the server was angular.js, by searching their github I found a NgController.java file which has an odd code segment:
public void renderHead(IHeaderResponse response) {
// add Google AngularJS reference
response.renderJavascriptReference(new ResourceReference(NgController.class, "angular.js"));
The actual class also implements IHeaderContributor, which is from the Apache Wicket package, not sure if this helps to troubleshoot the issue.
I also found this question which mentions FORWARD requests, I'm gonna try checking this out, but I'm still not sure what's going on.
Just a minor addition, it seems that the correct solution would be using Tomcat's Valve but that question has a comment mentioning that: [Filters]'re only overridable whenever webapp's /WEB-INF/web.xml has another one with same filter name.
Which is an impossible situation in this case, since I doubt the deployed app has a filter map with the same filter name.
I'll probably migrate the whole thing to the Valve Component to make sure it's server wide, but I still don't understand what's going on in this particular scenario.
ALSO: I forgot to mention that GitBlit has a console output when a user tries to connect, ex: 2016-05-13 13:53:38 [INFO ] 0 repositories identified with calculated folder sizes in 5 msecs and I just noticed that the filter hit system.out.println is being executed AFTER it, meaning somehow the request from the browser is not passing through it.
Upon closer inspection of this question, I've decided to migrate the servlet to a valve.
It was pretty straight forward.
I'll just mention that I had to add these two lines of code
HttpServletRequest servletReq = valveReq.getRequest();
HttpServletResponse servletRes = valveRes.getResponse();
To make the Valve work as expected, since the original filter has some rules based on the request and it would redirect the user if not authenticated.
I had the same problem and although I didn't find any answer to this problems I did some tests myself and I came to the conclusion that the /* url mapping on Tomcat's web.xml means anything below the root context.
Suppose this is what you have deployed on your Tomcat:
/ (root application)
/myApp1
/myApp2
If you then make a GET request to the URL /myApp1/users the filter won't be triggered because you are performing an operation on /myApp1 context.
If instead you make a GET request to the URL /myApp3/users then the filter will run, because now the context is /.
Unluckily, has I said, I have no source for this claim, apart from some personal tests and I don't quite understand how Tomcat default filters are supposed to work, so feel free to disprove me.

Spring Security with path variable parameters

I would like to create security rules based on custom url parameters (path variables).
In example. Let say I want to have user that has admin access for resources called Brand1 and Brand2 but has no access to resource called Brand3. We may edit resources using following links.
http://myapp/brand/edit/1
http://myapp/brand/edit/2
http://myapp/brand/edit/3
now in security context I would like to do something like that
<security:intercept-url pattern="/brand/edit/{brandId}"
access="hasRole('ROLE_ADMIN') or
#authorizationService.hasBrandPermission(
#brandId, principal.username)"/>
The only thing I get is username. BrandId is always null.
I used to do that with #PreAuthorize and it worked but now I would like to centralized security configuration in single xml file instead of spreading it across all controller classes. Moreover when I was using #PreAuthorize my access-denied-handler did not redirect me into denied page but display ugly AccessDeniedException insead.
I would really aprecieate any ideas.
Change the Spring Security version in your pom.xml to 4.1.0.RELEASE:
<spring-security.version>4.1.0.RELEASE</spring-security.version>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
You may need to clean your maven project after that.
(I know, it's an old question. Nonetheless, I faced same issue 3 years later).
you can try using regular expression.
you will need to add the attribute path-type="regex" in your http element or request-matcher="regex" if your using spring security 3.1
see the documentation for more details

Tomcat trying to resolve JSP files in RESTful Spring MVC Service

I am using Spring MVC to create a RESTful service, using the #Controller and #RequestMapping annotations to control responses. I am also using Maven as a dependency management system.
In one function, I use a URI template in my #RequestMapping to retrieve a variable from the GET request. This function returns JSON when it is complete.
Due to problems with the JSTL libraries as a result of using URI templates (essentially I was getting 500 status codes because of a ClassNotFoundException with a JSTL class), I had to add the following dependencies to my Maven POM file (these come from our private repository, but you should be able to understand what they are):
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2-rev-1</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
However, as a result of adding these, I now get 404 errors, because Tomcat (which is handling the requests under Spring) is trying to resolve my URI, which is usually
localhost:9095/DiagnosticToolService/demo-object/1/json (the 1 being my GET variable, of course)
to a file, specifically
localhost:9095/DiagnosticToolService/WEB-INF/jsp/demo-object/1/json.jsp
Of course, this file does not exist. How do I turn off this automatic JSP resolution in Tomcat so that it can work properly? Also, are those the dependencies I needed to add to fix the 500 error? The 500 error and the 404 error are shown below:
The 500 error
The 404 error
Are you using #ResponseBody on your controller method that produces JSON? from the description of the problem it looks like the request is not making it to your controller or the return value from the controller is interpreted as a view name.
Can you post the mapping you are using on the controller just the method signature?

Spring MVC REST : static files unaccessible because of url-pattern

My Spring Dispatcher servlet url-pattern is /* (as spring MVC REST suggests)
Now all the request are resolved by this Servlet. even CSS/JS/Images also get resolved and handled by servlet..
So, Spring MVC tries to find controller.. :(
How to bypass this? Is there any standard way out of this problem??
& Don't want to change url-pattern to /rest/* (so, other static resources get accessed by /css/ or /js etc.)
You can map your controllers to a smaller set of URLS (i.e. /app/*), and then rewrite the URLs that your users actually see so that they don't even know about. Have a look at the mvc-basic webapp sample, particularly web.xml and urlrewrite.xml to see how this is done.
Map the Spring dispatcher to some subsection of the URL space, and use Tuckey to rewrite URLs the user deals with.
http://www.example.org/app/controller/action -> http://www.example.org/controller/action
Just a heads-up update on this: the default rewrite configuration as defined in the Spring sample did not work out of the box for me. The rewrite rules for stylesheets, scripts, etc. were still processed to the /app/* rule, and subsequently handled by the DispatchServlet, which is not desirable.
I had to add the last="true" attribute to the styles/scripts/images rules to indicate that other rules should not apply, and I had to use the FreeMarker Spring URL macro in any CSS/JS include paths.
Just in case someone encounters the same problem.

Categories