How to use Servlet in Struts2 - servlets

How to use servlets together with Struts2?

I assume you want to know how to use a servlet in conjunction with Struts2 when you have mapped everything to the Struts2 filter.
You can use the following in your struts.xml:
<constant name="struts.action.excludePattern" value="/YourServlet"/>
You can exclude multiple patterns by separating them with a comma, such as:
<constant name="struts.action.excludePattern" value="/YourServlet,/YourOtherServlet"/>
More Information
Filter mapping for everthing to Struts2 besides one servlet?
Filters not working in Struts2

There are three ways to resolve this problem:
add constant tag in struts.xml
<constant name="struts.action.excludePattern" value="/YourServlet,/YourOtherServlet"/>
add suffix in servlet configuration in web.xml
<servlet-mapping>
<servlet-name>Authcode</servlet-name>
<url-pattern>/authcode.servlet</url-pattern>
</servlet-mapping>
Because in struts 2, it will only intercept all the request end with .action, if this request do not have any suffix, it will automatically add it. When we make our servlet url-pattern have a suffix, then struts 2 will not intercept it anymore.
implement a user-defined filter

Servlets technology is more low level architectural layer than Struts2. Even more Struts2 is embedded to your project as a filter (that is part of servlet technology).
So to add one more servlet just add to web.xml registration:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>class.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

If you need multi mapping servlet you can using:
<constant name="struts.action.excludePattern" value="/Servletname1, /Servletname2" />
But in struts, you should not using servlet url because it not unity. You can use ajax:
$.ajax({
url : "nameAction.action?param="+id,
type : "post",
data : {
'id' : id
},
success : function(data) {
// $('#result').html(data);
},
error : function(jqXHR, textStatus, errorThrown) {
$('#result').html("Error");
}
});

Related

Invoke servlet Filters from another servlet

I'm working on a CMS.
My code is inside the doGet() function of a servlet invoked at url "/market". I want a HttpServletRequestWrapper that would pass through all filters set for url "/page".
I expect these filters would update the request, so that an annotation processor could later inject dependencies with correct values.
I'm in a Tomcat server, so I should be able to cast to the right special object, and I don't have to be compliant to other servers.
An associated question is that using req.getRequestDispatcher(path).forward(requestWrapper, responseWrapper);, I was expecting the filters to be invoked. Should they ?
The javadoc says:
This method allows one servlet to do preliminary processing of a
request
Filters are by default mapped on the REQUEST dispatcher only. The below example of a filter mapping
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
is implicitly equivalent to
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
This means, the filter is only triggered on the "raw" incoming request, not on a forwarded request.
There are three more dispatchers: FORWARD, INCLUDE and ERROR. The RequestDispatcher#forward() triggers the FORWARD dispatcher. If you'd like to let your filter hook on that as well, then just add it:
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Note that you need to explicitly specify the REQUEST dispatcher here, otherwise it would assume that you're overriding it altogether and are only interested in FORWARD dispatcher.
Inside the filter, if you'd like to distinguish between a REQUEST and FORWARD, then you can then check that by determining the presence of a request attribute keyed with RequestDispatcher#FORWARD_REQUEST_URI
String forwardRequestURI = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if (forwardRequestURI != null) {
// Forward was triggered on the given URI.
}

Filter Liferay HttpRequest

I would like to filter (modify) HttpRequest, which is coming to target Liferay Servlet, intercept it and add some attributes. (for example User) and then redirect (forward) the request to the target servlet. I create new servlet that should work like interceptor, add the attribute (request.setAttribute("user", User)) and then either dispatcher.forward or response.redirect... This is only for testing purposes to be able to call some liferay functionality from tests.
The problem is that Liferay is filtering the request and add there its 7 attributes. I tried also create SimpleFilter, but its not called when target servlet is called, only when I create my own Servlet which extends HttpServlet.
So the question is, is it possible to tell liferay not to filter the requests or more important not to remove the attributes from the request? I have debugged the Liferay source code, catch the Filter Chain and on the 1. filter I see there original request, and at the end the requests contains those Liferay attributes.
Many thanks.
The target servlet is defined like this:
<servlet>
<servlet-name>targetServlet</servlet-name>
<servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
<init-param>
<param-name>servlet-class</param-name>
<param-value>org.springframework.web.context.support.HttpRequestHandlerServlet</param-value>
</init-param>
<init-param>
<param-name>sub-context</param-name>
<param-value>targetServlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Handler method mappings with Spring 3.2.6

I'm trying to learn web app development with Spring MVC framework and I'm not completely clear about how controller mappings work. It will be better if I show my config and code first and then explain what I don't understand.
Here's mapping in my web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
mapping in my controller class:
#Controller
#RequestMapping("/main/courses")
public class CourseController {
...
and mapping of the method in question in this controller:
#RequestMapping(value="", method = RequestMethod.GET)
public String getCourses(Model model) {
...
As you can see, value attribute is set to empty quotes and this is the only way this mapping works. If I change value attribute to "/", I get 404 error. I have other mappings in this controller that work fine, for example value="/add". The only problem is when I try to map to the root of this controller.
Is value="" a valid value? Why value="/" doesn't work?
The #RequestMapping used at the class level sets the base path mapping that all the handlers methods will resolved against.
In your example, that's
#RequestMapping("/main/courses")
When you specify another #RequestMapping on a method like
#RequestMapping("/add")
that is added as a path element. So the request would need to be to
/main/courses/add
If you have another like so
#RequestMapping("/")
then you add a new path element but the element itself is empty. So the request needs to be to
/main/courses/
With a mapping like
#RequestMapping("")
there is no new path element, it's just the empty String. So the request would need to be to
/main/courses

How to map servlet to /*, it fails with infinite loop and eventually StackOverflowError

I would like to map my servlet to /*, but it failed with an infinite loop.
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>my.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The java code is:
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response){
request.getRequestDispatcher("/WEB-INF/jsps/hello.jsp").forward(request, response);
}
}
If I map to /hello, everything works fine.
As the HelloServlet is mapped to /*, it will also be invoked on RequestDispatcher#forward() and cause the infinite loop.
How is this caused and how can I solve it?
This is not possible. The JSP should actually invoke container's builtin JspServlet. But the /* mapping definied by the webapp has a higher precedence.
You need to map the servlet on a more specific URL pattern like /pages/* and create a servlet filter which forwards non-static requests to that servlet. Yes, non-static requests (image/CSS/JS files) are also covered by /*, but they should not be processed by the servlet at all.
Assuming that you've all static resources in /resources folder, the following should do:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
With the following in filter's doFilter():
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/resources")) {
chain.doFilter(request, response); // Goes to container's own default servlet.
} else {
request.getRequestDispatcher("/pages" + uri).forward(request, response); // Goes to controller servlet.
}
This takes place fully transparently without any change to /pages in the URL. The forward to the JSP will not trigger the filter or the servlet. Filters do by default not kick in on forwards and the JSP forward path does not match the controller servlet's URL pattern any more.
Alternatively, if you have your own default servlet implementation, then you could map the servlet to / and let it delegate to the default servlet if the request isn't applicable as a front controller request. This is what Spring MVC is doing under the covers. Creating a default servlet is however not a trivial task as it should be capable of responding to conditional requests, caching requests, streaming requests, resume requests, directory listing requests, etecetera.
See also:
Difference between / and /* in servlet mapping url pattern
How to access static resources when mapping a global front controller servlet on /*
Design Patterns web based applications
This is possible duplicate to Servlet Filter going in infinite loop when FORWARD used in mapping in JSF
Otherwise should check what your JSP contains, it could be that it makes request for css or image files that can result in this behaviour. Also would recommend to try without a wildcard.

Filter is used as controller in Struts2

In struts2 why is a Filter is used as a controller instead of ActionServlet?
What is the advantage of using a Filter over ActionServlet?
As per Struts2 Budi Karnival struts2 book, There is one distinct advantage of using a filter over a servlet as a controller. With a filter you can conveniently choose to serve all the resources in your application, including static ones.
With a servlet, your controller only handles access to the dynamic part of the application. Note that the url-pattern element in the web.xml file in the previous application is
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>...</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
With such a setting, requests for static resources are not handled by the servlet controller, but by the container. You wouldn't want to handle static resources in your servlet controller because that would mean extra work.
A filter is different. A filter can opt to let through requests for static contents. To pass on a request, call the filterChain.doFilter method in the filter's doFilter method.
Consequently, employing a filter as the controller allows you to block all requests to the application, including request for static contents. You will then have the following setting in your deployment descriptor:
<filter>
<filter-name>filterDispatcher</filter-name>
<filter-class>...</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDispatcher</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Advantage of this filter : One thing for sure, you can easily protect your static files from curious eyes.
The following code will send an error message if a user tries to view a JavaScript file:
public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
if (uri.indexOf("/css/") != -1 && req.getHeader("referer") == null) {
res.sendError(HttpServletResponse.SC_FORBIDDEN);
} else {
// handle this request
}
}
It will not protect your code from the most determined people, but users can no longer type in the URL of your static file to view it. By the same token, you can protect your images so that no one can link to them at your expense.
Another advantage :
The introduction of Interceptors in Struts2 framework.It not just reduce our coding effort,but helps us write any code which we would have used filters for coding and necessary change in the web.xml as opposed to Struts1.So now any code that fits better in Filter can now moved to interceptors( which is more controllable than filters), all configuration can be controlled in struts.xml file, no need to touch the web.xml file
We generally Use a Filter when we want to filter and/or modify requests based on specific conditions.
For S2 to work it needs to perform certain reprocessing and modification work in order for a successful execution of your request while on other hands we use Servlet when we want to control, preprocess and/or post-process requests.
For controlling request S2 use Servlet under the hood but being hidden away to make the overall application structure more clean and easy to use.
This is what we have for Filters in The Java EE 6 Tutorial.
A filter is an object that can transform the header and content (or both) of a request or response. Filters differ from web components in that filters usually do not themselves create a response. Instead, a filter provides functionality that can be “attached” to any kind of web resource. Consequently, a filter should not have any dependencies on a web resource for which it is acting as a filter; this way, it can be composed with more than one type of web resource.

Resources