FacesServlet and URL Mapping in Web.xml - java

HI,
We are declaring the FacesServlet and its URL mapping in the Web.xml. From my understanding,
FacesServlet loaded only once at the server startup.
URL mapping is used only when first time JSP application accessed from the external context.
One of the new learner for JSF has asked me the questions, these two things are used only once by the application. Is it true? Also is there any other way by not including in the web.xml?
What I should answer?
Updated
For example, I am accessing the application using the URL http://localhost:8080/webapp/index.jsf. When we are accessing this URL, FacesServlet invoked and view is rendered. The following is my question:
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
In faces-config.xml we are giving the navigation cases as follows:
to-view-id>failure.jsp /to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?

FacesServlet loaded only once at the server startup.
Correct.
URL mapping is used only when first time JSP application accessed from the external context.
Incorrect. It's been tested on every incoming HttpServletRequest. How else should the container know which servlet to invoke?
Also is there any other way by not including in the web.xml?
If you're using a servletcontainer which supports Servlet 3.0, you can also do this by #WebServlet annotation. JSF 2.0, however, is designed to be backwards compatible with Servlet 2.5, so it doesn't ship with that annotation and you need to explicitly declare it in web.xml.
See also:
Servlets tag info page
Lifecycle of a JSP/Servlet webapplication
How servlets are initialized and used
Update as per the new series of questions (which should each belong in its own question, but ala)
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
This happens only if under the covers a forward by RequestDispatcher#forward() takes place. In a forward, the servletcontainer basically reuses the same HTTP request/response for a view (JSP/XHTML page). It does not force/instruct the webbrowser to send a brand new request. On the other hand, the HttpServletResponse#sendRedirect() will instruct the client (the webbrowser) to fire a new GET request and thus the URL will change. You can force this in the JSF sice by adding <redirect/> to the <navigation-case>. Note that since this causes a new request, all request scoped beans of the initial request will be lost.
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
The FacesServlet knows its own url-pattern.

Yes. while loading your application container will load web.xml and will extract the data for
particular URL pattern to servlet . when request comes it checks from memory that for this pattern which servlet to invoke and then if servlet is already loaded it will take it from memory otherwise it will create an instance of servlet and it will invoke doGet() or doPost() depending on the request type.
and there is another way to delcare URL mapping as from JAVAEE-6 by annotation
something like
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.WebServlet;
#WebServlet(
name = "SimpleServlet",
urlPatterns = {"/login"},
initParams = {
#InitParam(name = "param1", value = "value1"),
#InitParam(name = "param2", value = "value2")}
)
public class SimpleServlet {
}
In faces-config.xml we are giving the navigation cases as follows:
<to-view-id>failure.jsp </to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
it is view identifier not the URL FacesServlet will load that view upon invocation of that navigation case.

Related

How to make a servlet handle all URLs except JSPs [duplicate]

The familiar code:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My understanding is that /* maps to http://host:port/context/*.
How about /? It sure doesn't map to http://host:port/context root only. In fact, it will accept http://host:port/context/hello, but reject http://host:port/context/hello.jsp.
Can anyone explain how is http://host:port/context/hello mapped?
<url-pattern>/*</url-pattern>
The /* on a servlet overrides all other servlets, including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually, you'd like to use /* on a Filter only. It is able to let the request continue to any of the servlets listening on a more specific URL pattern by calling FilterChain#doFilter().
<url-pattern>/</url-pattern>
The / doesn't override any other servlet. It only replaces the servletcontainer's built in default servlet for all requests which doesn't match any other registered servlet. This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. The servletcontainer's built in default servlet is also capable of dealing with HTTP cache requests, media (audio/video) streaming and file download resumes. Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, which is not exactly trivial (JSF utility library OmniFaces has an open source example). This is thus also a bad URL pattern for servlets. As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's built in JSP servlet will be invoked, which is already by default mapped on the more specific URL pattern *.jsp.
<url-pattern></url-pattern>
Then there's also the empty string URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested. This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". I only have to admit that I'd intuitively expect the empty string URL pattern and the slash URL pattern / be defined exactly the other way round, so I can understand that a lot of starters got confused on this. But it is what it is.
Front Controller
In case you actually intend to have a front controller servlet, then you'd best map it on a more specific URL pattern like *.html, *.do, /pages/*, /app/*, etc. You can hide away the front controller URL pattern and cover static resources on a common URL pattern like /resources/*, /static/*, etc with help of a servlet filter. See also How to prevent static resources from being handled by front controller servlet which is mapped on /*. Noted should be that Spring MVC has a built in static resource servlet, so that's why you could map its front controller on / if you configure a common URL pattern for static resources in Spring. See also How to handle static content in Spring MVC?
I'd like to supplement BalusC's answer with the mapping rules and an example.
Mapping rules from Servlet 2.5 specification:
Map exact URL
Map wildcard paths
Map extensions
Map to the default servlet
In our example, there're three servlets. / is the default servlet installed by us. Tomcat installs two servlets to serve jsp and jspx. So to map http://host:port/context/hello
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Doesn't match any extensions, next.
Map to the default servlet, return.
To map http://host:port/context/hello.jsp
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Found extension servlet, return.
Perhaps you need to know how urls are mapped too, since I suffered 404 for hours. There are two kinds of handlers handling requests. BeanNameUrlHandlerMapping and SimpleUrlHandlerMapping. When we defined a servlet-mapping, we are using SimpleUrlHandlerMapping. One thing we need to know is these two handlers share a common property called alwaysUseFullPath which defaults to false.
false here means Spring will not use the full path to mapp a url to a controller. What does it mean? It means when you define a servlet-mapping:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
the handler will actually use the * part to find the controller. For example, the following controller will face a 404 error when you request it using /perfix/api/feature/doSomething
#Controller()
#RequestMapping("/perfix/api/feature")
public class MyController {
#RequestMapping(value = "/doSomething", method = RequestMethod.GET)
#ResponseBody
public String doSomething(HttpServletRequest request) {
....
}
}
It is a perfect match, right? But why 404. As mentioned before, default value of alwaysUseFullPath is false, which means in your request, only /api/feature/doSomething is used to find a corresponding Controller, but there is no Controller cares about that path. You need to either change your url to /perfix/perfix/api/feature/doSomething or remove perfix from MyController base #RequestingMapping.
I think Candy's answer is mostly correct. There is one small part I think otherwise.
To map host:port/context/hello.jsp
No exact URL servlets installed, next.
Found wildcard paths servlets, return.
I believe that why "/*" does not match host:port/context/hello because it treats "/hello" as a path instead of a file (since it does not have an extension).
The essential difference between /* and / is that a servlet with mapping /* will be selected before any servlet with an extension mapping (like *.html), while a servlet with mapping / will be selected only after extension mappings are considered (and will be used for any request which doesn't match anything else---it is the "default servlet").
In particular, a /* mapping will always be selected before a / mapping. Having either prevents any requests from reaching the container's own default servlet.
Either will be selected only after servlet mappings which are exact matches (like /foo/bar) and those which are path mappings longer than /* (like /foo/*). Note that the empty string mapping is an exact match for the context root (http://host:port/context/).
See Chapter 12 of the Java Servlet Specification, available in version 3.1 at http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.

Read index.html directly without exposing its path in URL

I have an index.html file in the following structure.
WEB-INF/dbName/type/id/index.html
Also, there are external css and js files in the same path.
I need to access this file without exposing its path in the browser.
Below is my controller class:
#Controller
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
#RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET, produces = MediaType.ALL_VALUE)
public String pod(HttpServletRequest request, #PathVariable String type, #PathVariable String id)
throws IOException {
String redirectUrl = "/dbName/" + type + "/" + id + "/index.html";
return "redirect:" + redirectUrl;
}
}
Resource mapping in servlet-dispatcher.xml:
<mvc:resources mapping="/dbName/**" location="/WEB-INF/dbName/" />
The resulting URL looks like this: localhost:8080/project/dbName/type/id/index.html
But, the expected URL is: localhost:8080/project/type/id/
This code exposes the URL to the resource in the browser. Then, I tried using forward instead of redirect. Then it doesn't expose the URL, but the external CSS and js used in index.html are not loaded.
Any help would be appreciated.
The contract of a view resolver specifies that a view resolver can return null to indicate the view could not be found. Not all view resolvers do this, however, because in some cases, the resolver simply cannot detect whether or not the view exists. For example, the InternalResourceViewResolver uses the RequestDispatcher internally, and dispatching is the only way to figure out if a JSP exists, but this action can only execute once. The same holds for the VelocityViewResolver and some others. Check the javadocs of the specific view resolver to see whether it reports non-existing views. Thus, putting an InternalResourceViewResolver in the chain in a place other than the last results in the chain not being fully inspected, because the InternalResourceViewResolver will always return a view!
Redirecting to Views
As mentioned previously, a controller typically returns a logical view name, which a view resolver resolves to a particular view technology. For view technologies such as JSPs that are processed through the Servlet or JSP engine, this resolution is usually handled through the combination of InternalResourceViewResolver and InternalResourceView, which issues an internal forward or include via the Servlet API’s RequestDispatcher.forward(..) method or RequestDispatcher.include() method. For other view technologies, such as Velocity, XSLT, and so on, the view itself writes the content directly to the response stream.
RedirectView
One way to force a redirect as the result of a controller response is for the controller to create and return an instance of Spring’s RedirectView. In this case, DispatcherServlet does not use the normal view resolution mechanism. Rather because it has been given the (redirect) view already, the DispatcherServlet simply instructs the view to do its work. The RedirectView in turn calls HttpServletResponse.sendRedirect() to send an HTTP redirect to the client browser.
If you use RedirectView and the view is created by the controller itself, it is recommended that you configure the redirect URL to be injected into the controller so that it is not baked into the controller but configured in the context along with the view names. The the section called “The redirect: prefix” facilitates this decoupling.
The redirect: prefix
While the use of RedirectView works fine, if the controller itself creates the RedirectView, there is no avoiding the fact that the controller is aware that a redirection is happening. This is really suboptimal and couples things too tightly. The controller should not really care about how the response gets handled. In general it should operate only in terms of view names that have been injected into it.
The special redirect: prefix allows you to accomplish this. If a view name is returned that has the prefix redirect:, the UrlBasedViewResolver (and all subclasses) will recognize this as a special indication that a redirect is needed. The rest of the view name will be treated as the redirect URL.
The net effect is the same as if the controller had returned a RedirectView, but now the controller itself can simply operate in terms of logical view names. A logical view name such as redirect:/myapp/some/resource will redirect relative to the current Servlet context, while a name such as redirect:http://myhost.com/some/arbitrary/path will redirect to an absolute URL.
The forward: prefix
It is also possible to use a special forward: prefix for view names that are ultimately resolved by UrlBasedViewResolver and subclasses. This creates an InternalResourceView (which ultimately does a RequestDispatcher.forward()) around the rest of the view name, which is considered a URL. Therefore, this prefix is not useful with InternalResourceViewResolver and InternalResourceView (for JSPs for example). But the prefix can be helpful when you are primarily using another view technology, but still want to force a forward of a resource to be handled by the Servlet/JSP engine. (Note that you may also chain multiple view resolvers, instead.)
As with the redirect: prefix, if the view name with the forward: prefix is injected into the controller, the controller does not detect that anything special is happening in terms of handling the response.
DOCS: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
The RequestDispatcher class and it's forward method like you've mentioned should work.
RequestDispatcher rd = req.getRequestDispatcher("index.html");
rd.forward(req, resp);
This should serve the index.html page nodifferently than visiting it directly.
It's confusing why the CSS and JS would fail to work using this method. I don't believe there is anything different between requesting /index.html or using a servlet to request index.html that would cause this. Maybe check that these files are correctly referenced in your HTML?
I know this would be better suited to a comment but I haven't yet earned enough reputation, sorry.
The redirect sends the URL back to browser first and then from browser another request is created, redirect can redirect to resources on different servers. Since the url with redirect action is sent back to browser, causes the browser to show the URL in client's address bar
Just use
request.getRequestDispathcer("url").forward(//required params);
Forward request is used to forward to resources available within the server from where the call is made. This transfer of control is done by the container internally and browser / client is not involved.

How to setThreadContextInheritable(true) via xml on Spring's dispatcherportlet and dispatcherservlet

I want to make the current request available to child threads without passing on the original request as method parameters through several layers. The application runs both as a servlet and as a portlet.
Normally, DispatcherServlet and DispatcherPortlet set the current request into a RequestContextHolder on the current thread. That way, a call thread has access to the current request. The request is not propagated to child threads.
In my case, the request spawns a subthread where it makes a ReST call using RestTemplate, and I need to access the original request in an ClientHttpRequestInterceptor that intercepts the RestTemplate. The request that is passed to intercept is useless, I need the original request that hit the server.
Both DispatcherServlet and DispatcherPortlet have a feature to pass on the RequestContext to child threads: setThreadContextInheritable(true). However, it seems not so easy to set that flag to true. There is no init-param which sets it, and usually you specify them in web.xml or portlet.xml.
Is there a way to customize a dispatcher portlet or servlet via their setters using xml configuration? The only way I found is to write a custom dispatcherservlet/portlet which sets the flag to true internally and use that in web.xml and portlet.xml.
There is no way to do this directly through XML configuration. You would need to do as you said and create a subclass of DispatcherServlet which internally calls setThreadContextInheritable(true).
The alternative is to perform your ServletContext configuration in Java. Spring provides a WebApplicationInitializer and a number of useful subtypes where you can register a customized DispatcherServlet (other servlets and filters).
You'd create your instance.
DispatcherServlet servlet = new DispatcherServlet(context);
servlet.setThreadContextInheritable(true);
and then register it
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);

How to get url request parameter from inside LIferay/IceFaces/JSF portlet backing bean

Is posible for a portlet to read a request parameter of its surrounding page?
E.g. the URL of the page the portlet resides in is http://example.com/mygroup/mypage?foo=bar Is it possible to read the "foo" parameter from a portlet that is on that page?
Portlet Container is Liferay 6.0.5.
P.S.
I have already tried:
com.liferay.portal.util.PortalUtil.getOriginalServletRequest(com.liferay.portal.util.PortalUtil.getHttpServletRequest((javax.portlet.PortletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest())).getParameter("foo")
but I always get null for productId
Thanks!
Have you tried
ExternalContext.getRequestParameterMap()
The following code will do the trick:
javax.portlet.PortletRequest pr = (javax.portlet.PortletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("javax.portlet.request");
java.lang.reflect.Method method = pr.getClass().getMethod("getOriginalHttpServletRequest");
HttpServletRequest httpServletRequest = (HttpServletRequest)method.invoke(pr, new Object[] {});
return httpServletRequest.getParameter(YOUR_PARAM_KEY);
In a partial submit, the icefaces ajax bridge (which replaces a usual jsf portlet bridge) is avoiding the normal portal action/render request, contacting directly the blocking servlet (in order to avoid invalidating other request-scoped portlets and in general, to be faster). Because of this, all those params/attributes which are set in a normal portal request are not set in ajax. They are set only in the initial GET type request for that page. So, actually what you should do is saving those params in the #PostConstruct or some other method of your controlling bean, and then reuse them later. (They wouldn't change in a partial submit anyway, right?).
Keep in mind though, that this will not work if you use IceFaces in conjuction with Spring (and their EL Resolver, since that eliminates your extended request scope).
if you are in JSF environment then try this:
String param = LiferayFacesContext.getInstance().getRequestQueryStringParameter("foo");

JSP:forward Question

I am just getting started on web app development. I have an index.jsp that has just ONE line.
< jsp:forward page="landing.do?"/>
What does
the above line do?
page="landing.do?" actually refer to?
what does the question mark "?" next to "landing.do?" signify?
As Bozho rightly pointed out, a servlet called "action" is mapped to handle "*.do" in my web.xml (as shown below).
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Now
How do I find out what the servlet "action" corresponding to "landing.do" actually does?
Thanks.
The <jsp:forward> forwards a client request to the url declared on the page attribute.
I also need to mention that in your example, you should have a / as first character inside your page declaration, if you want to specify a relative URL, i.e.:
This, in effect, is translated as a redirection to (if localhost)
http://localhost:8080/MyAPP/landing.do? (yours would have been translated to http://localhost:8080/MyAPPLanding.do?)
The ? allows you to append application/x-www-form-urlencoded parameters into your declaration.
More info here.
To know what landing.do does, do the following:
Go to your struts-config.xml (found in WEB-INF folder in your project) file and find any action (<action>) that a path="/landing") attribute.
Once you find your action, there's an attribute called type (inside that action). The type is a the class name of the action class that Struts calls to execute the action. The class name is fully qualified name.
Open the java file of the class (if it exists) and depending on the action (Action, DispatchAction, LookupDispatchAction), you will have to find its mappings and see what method Struts invokes.
In your example, my assumption will be based that your landing.do is of type Action. Therefore, read what the execute() method does. All actions actually, is execute() by Struts. The other actions are just Template Method patterns that knows what method to call by some mapping.
you probably have a servlet mapped to handle *.do in your web.xml
the ? means nothing here - generally it marks the start of get parameters (like ?param=value)
forward changes the current page with the specified, without the client knowing the change has happened.
This line will forward user to another page of the site, in particular to landing.do
page="landing.do?" actually refer to some page of the site landing.do. I believe this page is written with Struts framework. (But can be other)
what does the question mark "?" next to "landing.do?" mean nothing in this case. Generally after "?" there should be a list of request parameters. In this cases there will just be no parameters.
Update:
You should find servlet class which is mapped to that servlet name. After that you will be able to try to understand what that servlet class does. Also, look at the Struts tutorials or specification to get understanding of Struts framework workflows.

Categories