I have a struts-based webapp, and I would like the default "welcome" page to be an action. The only solutions I have found to this seem to be variations on making the welcome page a JSP that contains a redirect to the action. For example, in web.xml:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
and in index.jsp:
<%
response.sendRedirect("/myproject/MyAction.action");
%>
Surely there's a better way!
Personally, I'd keep the same setup you have now, but change the redirect for a forward. That avoids sending a header back to the client and having them make another request.
So, in particular, I'd replace the
<%
response.sendRedirect("/myproject/MyAction.action");
%>
in index.jsp with
<jsp:forward page="/MyAction.action" />
The other effect of this change is that the user won't see the URL in the address bar change from "http://server/myproject" to "http://server/myproject/index.jsp", as the forward happens internally on the server.
This is a pretty old thread but the topic discussed, i think, is still relevant. I use a struts tag - s:action to achieve this. I created an index.jsp in which i wrote this...
<s:action name="loadHomePage" namespace="/load" executeResult="true" />
As of the 2.4 version of the Servlet specification you are allowed to have a servlet in the welcome file list. Note that this may not be a URL (such as /myproject/MyAction.action). It must be a named servlet and you cannot pass a query string to the servlet. Your controller servlet would need to have a default action.
<servlet>
<servlet-name>MyController</servlet-name>
<servlet-class>com.example.MyControllerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyController</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>MyController</welcome-file>
</welcome-file-list>
"Surely there's a better way!"
There isn't. Servlet specifications (Java Servlet Specification 2.4, "SRV.9.10 Welcome Files" for instance) state:
The purpose of this mechanism is to allow the deployer to specify an ordered
list of partial URIs for the container to use for appending to URIs when there is a
request for a URI that corresponds to a directory entry in the WAR not mapped to
a Web component.
You can't map Struts on '/', because Struts kind of require to work with a file extension. So you're left to use an implicitely mapped component, such as a JSP or a static file. All the other solutions are just hacks. So keep your solution, it's perfectly readable and maintainable, don't bother looking further.
Something that I do is to put an empty file of the same name as your struts action and trick the container to call the struts action.
Ex. If your struts action is welcome.do, create an empty file named welcome.do. That should trick the container to call the Struts action.
It appears that a popular solution will not work in all containers... http://www.theserverside.com/discussions/thread.tss?thread_id=30190
I would create a filter and bounce all requests to root back with forward responce. Hacks with creating home.do page looks ugly to me (One more thing to remember for you and investigate for someone who will support your code).
Here two blogs with same technique:
http://technologicaloddity.com/2010/03/25/spring-welcome-file-without-redirect/
http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage
It require Servlet API >= v2.4:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
<url-pattern>/index.htm</url-pattern> <<== *1*
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.htm</welcome-file> <<== *2*
</welcome-file-list>
so you no longer need redirect.jsp in non-WEB-INF directory!!
there are this answer above but it is not clear about web app context
so
i do this:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>TilesDispatchServlet</servlet-name>
<servlet-class>org.apache.tiles.web.util.TilesDispatchServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TilesDispatchServlet</servlet-name>
<url-pattern>*.tiles</url-pattern>
</servlet-mapping>
And in index.jsp i just write:
<jsp:forward page="index.tiles" />
And i have index definition, named index and it all togather work fine and not depends on webapp context path.
I have configured like following. it worked perfect and no URL change also...
Create a dummy action like following in struts2.xml file. so whenever we access application like http://localhost:8080/myapp, it will forward that to dummy action and then it redirects to index.jsp / index.tiles...
<action name="">
<result type="tiles">/index.tiles</result>
</action>
w/o tiles
<action name="">
<result>/index.jsp</result>
</action>
may be we configure some action index.action in web.xml as <welcome-file>index.action</welcome-file>, and use that action to forward required page...
I am almost sure that the OP is the best solution(not sure about best practice, but it works perfectly, and actually is the solution my project leader and I prefer.)
Additionally, I find it can be combined with Spring security like this:
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize access="isAnonymous()">
<% response.sendRedirect("/myApp/login/login.action?error=false"); %>
</sec:authorize>
<sec:authorize access="isAuthenticated() and (hasRole('ADMIN') or hasRole('USER'))">
<% response.sendRedirect("/myApp/principal/principal.action"); %>
</sec:authorize>
<sec:authorize access="isAuthenticated() and hasRole('USER')">
<% response.sendRedirect("/myApp/user/userDetails.action"); %>
</sec:authorize>
By this, not only we have control over the first page to be the login form, but we control the flow AFTER user is login in, depending on his role. Works like a charm.
Below code can be used in struts.xml to load welcome page.
Execute some Action before loading a welcome page.
<!-- welcome page configuration -begin -->
<action name="" class="com.LoginAction">
<result name="success">login.jsp</result>
</action>
<!-- welcome page configuration -end -->
Return directly some JSP without execution of an Action.
<!-- welcome page configuration -begin -->
<action name="">
<result name="success">login.jsp</result>
</action>
<!-- welcome page configuration -end -->
No <welcome-file-list> is not needed in web.xml
Just add a filter above Strut's filter in web.xml like this:
<filter>
<filter-name>customfilter</filter-name>
<filter-class>com.example.CustomFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>customfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And add the following code in doFilter method of that CustomFilter class
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse)servletResponse;
if (! httpResponse.isCommitted()) {
if ((httpRequest.getContextPath() + "/").equals(httpRequest.getRequestURI())) {
httpResponse.sendRedirect(httpRequest.getContextPath() + "/MyAction");
}
else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
So that Filter will redirect to the action. You dont need any JSP to be placed outside WEB-INF as well.
This works as well reducing the need of a new servlet or jsp
<welcome-file-list>
<welcome-file>/MyAction.action</welcome-file>
</welcome-file-list>
This worked fine for me, too:
<welcome-file-list>
<welcome-file>MyAction.action</welcome-file>
</welcome-file-list>
I was not able to get the default action to execute when the user enters the webapp using the root of the web app (mywebapp/). There is a bug in struts 2.3.12 that won't go to the default action or use the welcome page when you use the root url. This will be a common occurrence. Once I changed back to struts 2.1.8 it worked fine.
Related
In JavaEE application.
I have index.html page as "welcome-file" in web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
I want to add Http Header into response for index.html
One way is use index.jsp instead of index.html and add inside an scriptlet:
<% response.addHeader("X-Frame-Options", "DENY"); %>
Is there any other way?
Is there an possiblility to add some kind of filter
For example something like:
WelcomeFileFilter {
void filter(HttpServletResponse response) {
response.addHeader("X-Frame-Options", "DENY");
}
}
Because I don't want to use index.jsp instead of index.html.
You can definitely add a filter,
try - responseheaderfilter
You can ask your web server/servlet container to add those headers for you. It will be configured in the server configuration files not in web.xml.
Or you can create a filter that will add headers for you. You'll have to configure the filter in your web.xml.
This stackoverflow answer show you how to configure jetty to add headers. This other stackoverflow answer shows you how to code a Filter that add headers.
The style sheet does not apply on my first JSF page. I've got a index.jsp which forwards to my first JSF page.
<html>
<head></head>
<body>
<jsp:forward page="./start.jsf" />
</body>
</html>
On start.jsf the style sheet does not apply but if I navigate to a second page my style sheet fully applies.
The second page was my first page before and I've had the same behaviour. Without changes, the second page works fine as long as the page is not the first one in row.
Therefore CSS and the page itself must be correct. I think it's a configuration issue.
Any ideas?
You should invoke the index page using an URL which invokes the FacesServlet. It's namely the one responsible for doing the JSF works. So you need to invoke it by index.jsf instead of index.jsp.
However, better is to get rid of this hacky index page altogether and define start.jsf as <welcome-file> in web.xml instead.
<welcome-file-list>
<welcome-file>start.jsf</welcome-file>
</welcome-file-list>
and supply an empty start.jsf file in the same folder next to the start.jsp file so that the servletcontainer will be fooled that the index page really exists (it namely by default doesn't check on any servlet mappings for the index page).
Try to use redirect instead of forward. You can do this like this in your jsp:
<% response.setStatus(301);
response.setHeader("Location", "/start.jsf?" + request.getQueryString());
response.setHeader("Connection", "close");
%>
or use
response.sendRedirect("/start.jsf?" + request.getQueryString());
It is not best way to solve problem, I use in my project tuckey urlrewrite:
<urlrewrite>
...
<rule enabled="true">
<from>^/$</from>
<to last="true">/index.jsf</to>
</rule>
...
</urlrewrite>
I have an action bean named HomeActionBean, which Stripes has bound to the URL "Home.action". The URL binding works. Now I would like to use "Home.action" as my welcome file, like this:
<welcome-file-list>
<welcome-file>Home.action</welcome-file>
</welcome-file-list>
This does not work with the default configuration from the Stripes quickstart guide. I get the error
A request made it through to some part of Stripes without being wrapped in a StripesRequestWrapper. [...]
I figured out that I can make it work if I add the line
<dispatcher>FORWARD</dispatcher>
to my web.xml like this:
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<servlet-name>StripesDispatcher</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
My question is: Is this the appropriate way of using a Stripes action as a welcome file? Does adding that line with "FORWARD" in it to my web.xml have other, possibly unwanted consequences?
To bind an action bean to the homepage URL you should use: #UrlBinding("/") like this:
#UrlBinding("/")
public class HomepageAction {
// .. action bean code..
}
I've read several docs and I don't get it: I know I'm doing something wrong but I don't understand what. I've got a website that is entirely dynamically generated: there's hardly any static content at all.
So, trying to understand JSP/Servlet, I've written my own "front controller" intercepting every single query, it looks like this:
<servlet-mapping>
<servlet-name>defaultservlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Basically I want any user request, like:
example.org
example.org/bar
example.org/foo.html
to all go through a default servlet which I've written.
The servlet then examines the URI and find to which .jsp the request must be dispatched, and then does, after having set all the attributes correctly, a:
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/jsp/index.jsp");
dispatcher.forward(req, resp);
When I'm using a url-pattern (in web.xml) like, say, *.html, everything works fine. But when I change it to /* (to really intercept everything), I enter an endless loop and it ends up with a... StackOverflow :)
When the request is dispatched, is the URI ".../WEB-INF/jsp/index.jsp" itself matched by the web.xml filter /* that I set?
EDIT apparently, no, because this is an exact mapping to index.jsp and hence it bypasses the web.xml url-pattern. So I still don't get how I can enter that endless loop.
How should I do if I want to intercept everything using a /* url-pattern and yet be able to dispatch/forward/?
I'm not asking about specs/Javadocs here: I'm really confused about the bigger picture and I'd need some explanation as to what could be going on.
Am I not supposed to intercept really everything?
If I can intercept everything, what should I be aware of regarding forwarding/dispatching?
Unfortunately, Serlvet spec doesn't allow to create a servlet mapping to match only incoming request, not forwards. However, this can be done for filter mappings (and by default filter mappings match only incoming requests).
So, the typical solution for intercepting everything with a single servlet is to use a UrlRewriteFilter:
<filter>
<filter-name>urlRewrite</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewrite</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>application</servlet-name>
<servlet-class>...</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>application</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
/WEB-INF/urlrewrite.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
"http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite default-match-type="wildcard">
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
This way also allows you to specify exceptions from /* mapping for static files.
Try using struts in which front controller pattern is inbuilt. There you will have a action class and you can define forwards in struts-config file using which you can easily manage the forwards.
Go through the tutorial http://www.roseindia.net/struts/struts2/index.shtml. Hope this helps you.
I want to create a JSP page or servlet that will work in 2 ways.
A user visits their own profile page:
http//something.com/profile/
Or they visit their friends page:
http://something.com/profile/FriendsName
They could also visit their own page through an explicit URL like:
http://something.com/profile/YourName
I have a servlet-mapping setup as follows to map any requests to /profile to my JSP that will handle that request.
<servlet>
<servlet-name>Profile</servlet-name>
<jsp-file>/profile.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Profile</servlet-name>
<url-pattern>/profile</url-pattern>
</servlet-mapping>
Then I was thinking I could setup a filter that will parse the HTTPServletRequest's URL to read after the /profile/.
<filter>
<filter-name>profile-filter</filter-name>
<filter-class>ProfileFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>profile-filter</filter-name>
<url-pattern>/profile*</url-pattern>
</filter-mapping>
Now the filter could set attributes in the HttpServletRequest, how would i go about pulling those out in the JSP page to check if a user name was specified and check if your own name was set?
How would I go about creating a page scoped bean in the ServletFilter so I could use in the JSP page using jspBean like this:
<jsp:useBean id="profileInfo" scope="page" class="ProfileInfo" />
I think a filter only serves to artificially break the logic apart. You can very easily determine the value of the portion of the URL that doesn't match the url-pattern described in the web.xml. The HttpServletRequest class has a method that returns this value for you, it's called getPathInfo(). Here's an example:
<%
String path = request.getPathInfo();
if (path == null || "".equalsIgnoreCase(path)) {
// The path was empty, display the current user's profile
} else {
// Display the named profile
}
%>
This doesn't help you at all with the request beans, but I think it helps with the design.
I'm not completely following the question, but if you want a jsp to access request parameters or attributes, just do:
<%
String parameter = request.getParameter("parameter");
String attribute = request.getAttribute("attribute");
%>
You can also get access to the request url, etc... if you need to do anything with those.
Personally, I'd recommend that you use a servlet to handle your requests, and forward to the jsp of your choosing (possibly after setting session information that the jsp can use).
Using server level filters and request attributes for this kind of thing may be a bit overkill, but only you know your project's true requirements.